Build fix, updating API changes from Tinymail
[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         GtkWidget *header_view; 
1566
1567         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1568
1569         folder_view = modest_main_window_get_child_widget (main_window,
1570                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1571         if (!folder_view)
1572                 return;
1573
1574         header_view = modest_main_window_get_child_widget (main_window,
1575                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1576         
1577         if (!header_view)
1578                 return;
1579
1580         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1581         
1582         if (folder && TNY_IS_FOLDER (folder)) {
1583                 gchar *folder_name;
1584                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1585                                                    _("Please enter a new name for the folder"));
1586
1587                 if (folder_name != NULL && strlen (folder_name) > 0) {
1588                         ModestMailOperation *mail_op;
1589
1590                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1591                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1592                                                          mail_op);
1593
1594                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1595
1596                         modest_mail_operation_rename_folder (mail_op,
1597                                                              TNY_FOLDER (folder),
1598                                                              (const gchar *) folder_name);
1599
1600                         g_object_unref (mail_op);
1601                         g_free (folder_name);
1602                 }
1603                 g_object_unref (folder);
1604         }
1605 }
1606
1607 static void
1608 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1609 {
1610         TnyFolderStore *folder;
1611         GtkWidget *folder_view;
1612         gint response;
1613         gchar *message;
1614         
1615         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1616
1617         folder_view = modest_main_window_get_child_widget (main_window,
1618                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1619         if (!folder_view)
1620                 return;
1621
1622         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1623
1624         /* Show an error if it's an account */
1625         if (!TNY_IS_FOLDER (folder)) {
1626                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1627                                                         _("mail_in_ui_folder_delete_error"));
1628                 return ;
1629         }
1630
1631         /* Ask the user */      
1632         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1633                                     tny_folder_get_name (TNY_FOLDER (folder)));
1634         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1635                                                             (const gchar *) message);
1636         g_free (message);
1637
1638         if (response == GTK_RESPONSE_OK) {
1639                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1640
1641                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1642                                                  mail_op);
1643                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1644
1645                 /* Show error if happened */
1646                 if (modest_mail_operation_get_error (mail_op))
1647                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1648                                                                 _("mail_in_ui_folder_delete_error"));
1649
1650                 g_object_unref (G_OBJECT (mail_op));
1651         }
1652
1653         g_object_unref (G_OBJECT (folder));
1654 }
1655
1656 void 
1657 modest_ui_actions_on_delete_folder (GtkAction *action,
1658                                      ModestMainWindow *main_window)
1659 {
1660         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1661
1662         delete_folder (main_window, FALSE);
1663 }
1664
1665 void 
1666 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1667 {
1668         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1669         
1670         delete_folder (main_window, TRUE);
1671 }
1672
1673 void
1674 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1675                                          const gchar* server_account_name,
1676                                          gchar **username,
1677                                          gchar **password, 
1678                                          gboolean *cancel, 
1679                                          gboolean *remember,
1680                                          ModestMainWindow *main_window)
1681 {
1682         g_return_if_fail(server_account_name);
1683         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1684         
1685 #ifdef MODEST_PLATFORM_MAEMO
1686         /* Maemo uses a different (awkward) button order,
1687          * It should probably just use gtk_alternative_dialog_button_order ().
1688          */
1689         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1690                                               NULL,
1691                                               GTK_DIALOG_MODAL,
1692                                               GTK_STOCK_OK,
1693                                               GTK_RESPONSE_ACCEPT,
1694                                               GTK_STOCK_CANCEL,
1695                                               GTK_RESPONSE_REJECT,
1696                                               NULL);
1697 #else
1698         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1699                                               NULL,
1700                                               GTK_DIALOG_MODAL,
1701                                               GTK_STOCK_CANCEL,
1702                                               GTK_RESPONSE_REJECT,
1703                                               GTK_STOCK_OK,
1704                                               GTK_RESPONSE_ACCEPT,
1705                                               NULL);
1706 #endif /* MODEST_PLATFORM_MAEMO */
1707
1708         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1709         
1710         gchar *server_name = modest_server_account_get_hostname (
1711                 modest_runtime_get_account_mgr(), server_account_name);
1712         
1713         /* This causes a warning because the logical ID has no %s in it, 
1714          * though the translation does, but there is not much we can do about that: */
1715         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1716         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1717                             FALSE, FALSE, 0);
1718         g_free (txt);
1719         g_free (server_name);
1720         server_name = NULL;
1721
1722         /* username: */
1723         gchar *initial_username = modest_server_account_get_username (
1724                 modest_runtime_get_account_mgr(), server_account_name);
1725         
1726         GtkWidget *entry_username = gtk_entry_new ();
1727         if (initial_username)
1728                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1729         /* Dim this if a connection has ever succeeded with this username,
1730          * as per the UI spec: */
1731         const gboolean username_known = 
1732                 modest_server_account_get_username_has_succeeded(
1733                         modest_runtime_get_account_mgr(), server_account_name);
1734         gtk_widget_set_sensitive (entry_username, !username_known);
1735         
1736 #ifdef MODEST_PLATFORM_MAEMO
1737         /* Auto-capitalization is the default, so let's turn it off: */
1738         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1739         
1740         /* Create a size group to be used by all captions.
1741          * Note that HildonCaption does not create a default size group if we do not specify one.
1742          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1743         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1744         
1745         GtkWidget *caption = hildon_caption_new (sizegroup, 
1746                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1747         gtk_widget_show (entry_username);
1748         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1749                 FALSE, FALSE, MODEST_MARGIN_HALF);
1750         gtk_widget_show (caption);
1751 #else 
1752         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1753                             TRUE, FALSE, 0);
1754 #endif /* MODEST_PLATFORM_MAEMO */      
1755                             
1756         /* password: */
1757         GtkWidget *entry_password = gtk_entry_new ();
1758         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1759         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1760         
1761 #ifdef MODEST_PLATFORM_MAEMO
1762         /* Auto-capitalization is the default, so let's turn it off: */
1763         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1764                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1765         
1766         caption = hildon_caption_new (sizegroup, 
1767                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1768         gtk_widget_show (entry_password);
1769         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1770                 FALSE, FALSE, MODEST_MARGIN_HALF);
1771         gtk_widget_show (caption);
1772         g_object_unref (sizegroup);
1773 #else 
1774         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1775                             TRUE, FALSE, 0);
1776 #endif /* MODEST_PLATFORM_MAEMO */      
1777                                 
1778 /* This is not in the Maemo UI spec:
1779         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1780         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1781                             TRUE, FALSE, 0);
1782 */
1783
1784         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1785         
1786         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1787                 if (username) {
1788                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1789                         
1790                         modest_server_account_set_username (
1791                                  modest_runtime_get_account_mgr(), server_account_name, 
1792                                  *username);
1793                                  
1794                         const gboolean username_was_changed = 
1795                                 (strcmp (*username, initial_username) != 0);
1796                         if (username_was_changed) {
1797                                 /* To actually use a changed username, 
1798                                  * we must reset the connection, according to pvanhoof.
1799                                  * This _might_ be a sensible way to do that: */
1800                                  TnyDevice *device = modest_runtime_get_device();
1801                                  tny_device_force_offline (device);
1802                                  tny_device_force_online (device);
1803                         }
1804                 }
1805                         
1806                 if (password) {
1807                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1808                         
1809                         /* We do not save the password in the configuration, 
1810                          * because this function is only called for passwords that should 
1811                          * not be remembered:
1812                         modest_server_account_set_password (
1813                                  modest_runtime_get_account_mgr(), server_account_name, 
1814                                  *password);
1815                         */
1816                 }
1817                 
1818                 if (cancel)
1819                         *cancel   = FALSE;
1820                         
1821         } else {
1822                 if (username)
1823                         *username = NULL;
1824                         
1825                 if (password)
1826                         *password = NULL;
1827                         
1828                 if (cancel)
1829                         *cancel   = TRUE;
1830         }
1831
1832 /* This is not in the Maemo UI spec:
1833         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1834                 *remember = TRUE;
1835         else
1836                 *remember = FALSE;
1837 */
1838
1839         gtk_widget_destroy (dialog);
1840 }
1841
1842 void
1843 modest_ui_actions_on_cut (GtkAction *action,
1844                           ModestWindow *window)
1845 {
1846         GtkWidget *focused_widget;
1847
1848         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1849         if (GTK_IS_EDITABLE (focused_widget)) {
1850                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1851         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1852                 GtkTextBuffer *buffer;
1853                 GtkClipboard *clipboard;
1854
1855                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1856                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1857                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1858         }
1859 }
1860
1861 void
1862 modest_ui_actions_on_copy (GtkAction *action,
1863                            ModestWindow *window)
1864 {
1865         GtkClipboard *clipboard;
1866         GtkWidget *focused_widget;
1867
1868         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1869         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1870         if (GTK_IS_LABEL (focused_widget)) {
1871                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1872         } else if (GTK_IS_EDITABLE (focused_widget)) {
1873                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1874         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1875                 GtkTextBuffer *buffer;
1876
1877                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1878                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1879         }
1880 }
1881
1882 void
1883 modest_ui_actions_on_undo (GtkAction *action,
1884                            ModestWindow *window)
1885 {
1886         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1887                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1888         } else {
1889                 g_return_if_reached ();
1890         }
1891 }
1892
1893 void
1894 modest_ui_actions_on_paste (GtkAction *action,
1895                             ModestWindow *window)
1896 {
1897         GtkWidget *focused_widget;
1898
1899         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1900         if (GTK_IS_EDITABLE (focused_widget)) {
1901                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1902         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1903                 GtkTextBuffer *buffer;
1904                 GtkClipboard *clipboard;
1905
1906                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1907                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1908                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1909         }
1910 }
1911
1912 void
1913 modest_ui_actions_on_select_all (GtkAction *action,
1914                                  ModestWindow *window)
1915 {
1916         GtkWidget *focused_widget;
1917
1918         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1919         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
1920                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
1921         } else if (GTK_IS_LABEL (focused_widget)) {
1922                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1923         } else if (GTK_IS_EDITABLE (focused_widget)) {
1924                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1925         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1926                 GtkTextBuffer *buffer;
1927                 GtkTextIter start, end;
1928
1929                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1930                 gtk_text_buffer_get_start_iter (buffer, &start);
1931                 gtk_text_buffer_get_end_iter (buffer, &end);
1932                 gtk_text_buffer_select_range (buffer, &start, &end);
1933         }
1934 }
1935
1936 void
1937 modest_ui_actions_on_mark_as_read (GtkAction *action,
1938                                    ModestWindow *window)
1939 {       
1940         g_return_if_fail (MODEST_IS_WINDOW(window));
1941                 
1942         /* Mark each header as read */
1943         do_headers_action (window, headers_action_mark_as_read, NULL);
1944 }
1945
1946 void
1947 modest_ui_actions_on_mark_as_unread (GtkAction *action,
1948                                      ModestWindow *window)
1949 {       
1950         g_return_if_fail (MODEST_IS_WINDOW(window));
1951                 
1952         /* Mark each header as read */
1953         do_headers_action (window, headers_action_mark_as_unread, NULL);
1954 }
1955
1956 void
1957 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1958                                   GtkRadioAction *selected,
1959                                   ModestWindow *window)
1960 {
1961         gint value;
1962
1963         value = gtk_radio_action_get_current_value (selected);
1964         if (MODEST_IS_WINDOW (window)) {
1965                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1966         }
1967 }
1968
1969 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1970                                                         GtkRadioAction *selected,
1971                                                         ModestWindow *window)
1972 {
1973         TnyHeaderFlags flags;
1974         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1975
1976         flags = gtk_radio_action_get_current_value (selected);
1977         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1978 }
1979
1980 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1981                                                            GtkRadioAction *selected,
1982                                                            ModestWindow *window)
1983 {
1984         gint file_format;
1985
1986         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1987
1988         file_format = gtk_radio_action_get_current_value (selected);
1989         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1990 }
1991
1992
1993 void     
1994 modest_ui_actions_on_zoom_plus (GtkAction *action,
1995                                 ModestWindow *window)
1996 {
1997         g_return_if_fail (MODEST_IS_WINDOW (window));
1998
1999         modest_window_zoom_plus (MODEST_WINDOW (window));
2000 }
2001
2002 void     
2003 modest_ui_actions_on_zoom_minus (GtkAction *action,
2004                                  ModestWindow *window)
2005 {
2006         g_return_if_fail (MODEST_IS_WINDOW (window));
2007
2008         modest_window_zoom_minus (MODEST_WINDOW (window));
2009 }
2010
2011 void     
2012 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2013                                            ModestWindow *window)
2014 {
2015         ModestWindowMgr *mgr;
2016         gboolean fullscreen, active;
2017         g_return_if_fail (MODEST_IS_WINDOW (window));
2018
2019         mgr = modest_runtime_get_window_mgr ();
2020
2021         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2022         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2023
2024         if (active != fullscreen) {
2025                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2026                 gtk_window_present (GTK_WINDOW (window));
2027         }
2028 }
2029
2030 void
2031 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2032                                         ModestWindow *window)
2033 {
2034         ModestWindowMgr *mgr;
2035         gboolean fullscreen;
2036
2037         g_return_if_fail (MODEST_IS_WINDOW (window));
2038
2039         mgr = modest_runtime_get_window_mgr ();
2040         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2041         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2042
2043         gtk_window_present (GTK_WINDOW (window));
2044 }
2045
2046 /* 
2047  * Used by modest_ui_actions_on_details to call do_headers_action 
2048  */
2049 static void
2050 headers_action_show_details (TnyHeader *header, 
2051                              ModestWindow *window,
2052                              gpointer user_data)
2053
2054 {
2055         GtkWidget *dialog;
2056         
2057         /* Create dialog */
2058         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2059
2060         /* Run dialog */
2061         gtk_widget_show_all (dialog);
2062         gtk_dialog_run (GTK_DIALOG (dialog));
2063
2064         gtk_widget_destroy (dialog);
2065 }
2066
2067 /*
2068  * Show the folder details in a ModestDetailsDialog widget
2069  */
2070 static void
2071 show_folder_details (TnyFolder *folder, 
2072                      GtkWindow *window)
2073 {
2074         GtkWidget *dialog;
2075         
2076         /* Create dialog */
2077         dialog = modest_details_dialog_new_with_folder (window, folder);
2078
2079         /* Run dialog */
2080         gtk_widget_show_all (dialog);
2081         gtk_dialog_run (GTK_DIALOG (dialog));
2082
2083         gtk_widget_destroy (dialog);
2084 }
2085
2086 /*
2087  * Show the header details in a ModestDetailsDialog widget
2088  */
2089 void     
2090 modest_ui_actions_on_details (GtkAction *action, 
2091                               ModestWindow *win)
2092 {
2093         TnyList * headers_list;
2094         TnyIterator *iter;
2095         TnyHeader *header;              
2096
2097         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2098                 TnyMsg *msg;
2099
2100                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2101                 if (!msg) {
2102                         return;
2103                 } else {
2104                         headers_list = get_selected_headers (win);
2105                         if (!headers_list)
2106                                 return;
2107
2108                         iter = tny_list_create_iterator (headers_list);
2109
2110                         header = TNY_HEADER (tny_iterator_get_current (iter));
2111                         headers_action_show_details (header, win, NULL);
2112                         g_object_unref (header);
2113
2114                         g_object_unref (iter);
2115                 }
2116         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2117                 GtkWidget *folder_view, *header_view;
2118
2119                 /* Check which widget has the focus */
2120                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2121                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2122                 if (gtk_widget_is_focus (folder_view)) {
2123                         TnyFolder *folder;
2124
2125                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2126
2127                         /* Show only when it's a folder */
2128                         if (!folder || !TNY_IS_FOLDER (folder))
2129                                 return;
2130
2131                         show_folder_details (folder, GTK_WINDOW (win));
2132
2133                 } else {
2134                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2135                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2136                         /* Show details of each header */
2137                         do_headers_action (win, headers_action_show_details, header_view);
2138                 }
2139         }
2140 }
2141
2142 void     
2143 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2144                                      ModestMsgEditWindow *window)
2145 {
2146         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2147
2148         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2149 }
2150
2151 void     
2152 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2153                                       ModestMsgEditWindow *window)
2154 {
2155         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2156
2157         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2158 }
2159
2160 void
2161 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2162                                        ModestMainWindow *main_window)
2163 {
2164         ModestConf *conf;
2165         
2166         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2167
2168         conf = modest_runtime_get_conf ();
2169         
2170         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2171                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2172         else
2173                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2174 }
2175
2176 void 
2177 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2178                                      ModestWindow *window)
2179 {
2180         gboolean active, fullscreen = FALSE;
2181         ModestWindowMgr *mgr;
2182
2183         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2184
2185         /* Check if we want to toggle the toolbar vuew in fullscreen
2186            or normal mode */
2187         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2188                      "ViewShowToolbarFullScreen")) {
2189                 fullscreen = TRUE;
2190         }
2191
2192         /* Toggle toolbar */
2193         mgr = modest_runtime_get_window_mgr ();
2194         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2195 }
2196
2197 void     
2198 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2199                                            ModestMsgEditWindow *window)
2200 {
2201         modest_msg_edit_window_select_font (window);
2202 }
2203
2204 void
2205 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2206                                                   const gchar *display_name,
2207                                                   GtkWindow *window)
2208 {
2209         /* Do not change the application name if the widget has not
2210            the focus. This callback could be called even if the folder
2211            view has not the focus, because the handled signal could be
2212            emitted when the folder view is redrawn */
2213         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2214                 if (display_name)
2215                         gtk_window_set_title (window, display_name);
2216                 else
2217                         gtk_window_set_title (window, " ");
2218         }
2219 }
2220
2221 void
2222 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2223 {
2224         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2225         modest_msg_edit_window_select_contacts (window);
2226 }
2227
2228 void
2229 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2230 {
2231         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2232         modest_msg_edit_window_check_names (window);
2233 }
2234
2235
2236 static GtkWidget*
2237 create_move_to_dialog (ModestWindow *win,
2238                        GtkWidget *folder_view,
2239                        GtkWidget **tree_view)
2240 {
2241         GtkWidget *dialog, *scroll;
2242
2243         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2244                                               GTK_WINDOW (win),
2245                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2246                                               GTK_STOCK_OK,
2247                                               GTK_RESPONSE_ACCEPT,
2248                                               GTK_STOCK_CANCEL,
2249                                               GTK_RESPONSE_REJECT,
2250                                               NULL);
2251
2252         /* Create scrolled window */
2253         scroll = gtk_scrolled_window_new (NULL, NULL);
2254         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2255                                          GTK_POLICY_AUTOMATIC,
2256                                          GTK_POLICY_AUTOMATIC);
2257
2258         /* Create folder view */
2259         *tree_view = modest_folder_view_new (NULL);
2260         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2261                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2262         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2263
2264         /* Add scroll to dialog */
2265         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2266                             scroll, FALSE, FALSE, 0);
2267
2268         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2269
2270         return dialog;
2271 }
2272
2273 /*
2274  * Returns TRUE if at least one of the headers of the list belongs to
2275  * a message that has been fully retrieved.
2276  */
2277 static gboolean
2278 has_retrieved_msgs (TnyList *list)
2279 {
2280         TnyIterator *iter;
2281         gboolean found = FALSE;
2282
2283         iter = tny_list_create_iterator (list);
2284         while (tny_iterator_is_done (iter) && !found) {
2285                 TnyHeader *header;
2286                 TnyHeaderFlags flags;
2287
2288                 header = TNY_HEADER (tny_iterator_get_current (iter));
2289                 flags = tny_header_get_flags (header);
2290                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2291                         found = TRUE;
2292
2293                 if (!found)
2294                         tny_iterator_next (iter);
2295         }
2296         g_object_unref (iter);
2297
2298         return found;
2299 }
2300
2301 /*
2302  * Shows a confirmation dialog to the user when we're moving messages
2303  * from a remote server to the local storage. Returns the dialog
2304  * response. If it's other kind of movement the it always returns
2305  * GTK_RESPONSE_OK
2306  */
2307 static gint
2308 msgs_move_to_confirmation (GtkWindow *win,
2309                            TnyFolder *dest_folder,
2310                            TnyList *headers)
2311 {
2312         gint response = GTK_RESPONSE_OK;
2313
2314         /* If the destination is a local folder */
2315         if (modest_tny_folder_is_local_folder (dest_folder)) {
2316                 TnyFolder *src_folder;
2317                 TnyIterator *iter;
2318                 TnyHeader *header;
2319
2320                 /* Get source folder */
2321                 iter = tny_list_create_iterator (headers);
2322                 header = TNY_HEADER (tny_iterator_get_current (iter));
2323                 src_folder = tny_header_get_folder (header);
2324                 g_object_unref (header);
2325                 g_object_unref (iter);
2326
2327                 /* If the source is a remote folder */
2328                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2329                         const gchar *message;
2330                         
2331                         if (tny_list_get_length (headers) == 1)
2332                                 if (has_retrieved_msgs (headers))
2333                                         message = _("mcen_nc_move_retrieve");
2334                                 else
2335                                         message = _("mcen_nc_move_header");
2336                         else
2337                                 if (has_retrieved_msgs (headers))
2338                                         message = _("mcen_nc_move_retrieves");
2339                                 else
2340                                         message = _("mcen_nc_move_headers");
2341                         
2342                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2343                                                                             (const gchar *) message);
2344                 }
2345         }
2346         return response;
2347 }
2348
2349
2350 static void
2351 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2352 {
2353         ModestMsgViewWindow *self = NULL;
2354         gboolean found = FALSE;
2355
2356         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2357         self = MODEST_MSG_VIEW_WINDOW (object);
2358
2359         found = modest_msg_view_window_select_first_message (self);
2360         g_return_if_fail (found);
2361 }
2362
2363 /*
2364  * UI handler for the "Move to" action when invoked from the
2365  * ModestMainWindow
2366  */
2367 static void 
2368 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2369                                           ModestMainWindow *win)
2370 {
2371         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2372         gint result;
2373         TnyFolderStore *folder_store;
2374         ModestMailOperation *mail_op = NULL;
2375
2376         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2377
2378         /* Get the folder view */
2379         folder_view = modest_main_window_get_child_widget (win,
2380                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2381
2382         /* Create and run the dialog */
2383         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2384         result = gtk_dialog_run (GTK_DIALOG(dialog));
2385         g_object_ref (tree_view);
2386
2387         /* We do this to save an indentation level ;-) */
2388         if (result != GTK_RESPONSE_ACCEPT)
2389                 goto end;
2390
2391         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2392
2393         if (TNY_IS_ACCOUNT (folder_store))
2394                 goto end;
2395
2396         /* Get folder or messages to transfer */
2397         if (gtk_widget_is_focus (folder_view)) {
2398                 TnyFolderStore *src_folder;
2399                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2400
2401                 if (TNY_IS_FOLDER (src_folder)) {
2402                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2403                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2404                                                          mail_op);
2405
2406                         modest_mail_operation_xfer_folder_async (mail_op, 
2407                                                                  TNY_FOLDER (src_folder),
2408                                                                  folder_store,
2409                                                                  TRUE);
2410                         g_object_unref (G_OBJECT (mail_op));
2411                 }
2412
2413                 /* Frees */
2414                 g_object_unref (G_OBJECT (src_folder));
2415         } else {
2416                 GtkWidget *header_view;
2417                 header_view = modest_main_window_get_child_widget (win,
2418                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
2419                 if (gtk_widget_is_focus (header_view)) {
2420                         TnyList *headers;
2421                         gint response;
2422
2423                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2424
2425                         /* Ask for user confirmation */
2426                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2427                                                               TNY_FOLDER (folder_store), 
2428                                                               headers);
2429
2430                         /* Transfer messages */
2431                         if (response == GTK_RESPONSE_OK) {
2432                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2433                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2434                                                                  mail_op);
2435
2436                                 modest_mail_operation_xfer_msgs (mail_op, 
2437                                                                  headers,
2438                                                                  TNY_FOLDER (folder_store),
2439                                                                  TRUE,
2440                                                                  NULL,
2441                                                                  NULL);
2442                                 g_object_unref (G_OBJECT (mail_op));
2443                         }
2444                         g_object_unref (headers);
2445                 }
2446         }
2447         g_object_unref (folder_store);
2448
2449  end:
2450         gtk_widget_destroy (dialog);
2451 }
2452
2453
2454 /*
2455  * UI handler for the "Move to" action when invoked from the
2456  * ModestMsgViewWindow
2457  */
2458 static void 
2459 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2460                                               ModestMsgViewWindow *win)
2461 {
2462         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2463         gint result;
2464         ModestMainWindow *main_window;
2465         TnyHeader *header;
2466         TnyList *headers;
2467
2468         /* Get the folder view */
2469         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2470         folder_view = modest_main_window_get_child_widget (main_window,
2471                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2472
2473         /* Create and run the dialog */
2474         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2475         result = gtk_dialog_run (GTK_DIALOG(dialog));
2476         g_object_ref (tree_view);
2477
2478         if (result == GTK_RESPONSE_ACCEPT) {
2479                 TnyFolderStore *folder_store;
2480                 gint response;
2481
2482                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2483
2484                 /* Create header list */
2485                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2486                 headers = tny_simple_list_new ();
2487                 tny_list_prepend (headers, G_OBJECT (header));
2488                 g_object_unref (header);
2489
2490                 /* Ask user for confirmation. MSG-NOT404 */
2491                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2492                                                       TNY_FOLDER (folder_store), 
2493                                                       headers);
2494
2495                 /* Transfer current msg */
2496                 if (response == GTK_RESPONSE_OK) {
2497                         ModestMailOperation *mail_op;
2498
2499                         /* Create mail op */
2500                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2501                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2502                                                          mail_op);
2503                         
2504                         /* Transfer messages */
2505                         modest_mail_operation_xfer_msgs (mail_op, 
2506                                                          headers,
2507                                                          TNY_FOLDER (folder_store),
2508                                                          TRUE,
2509                                                          tranasfer_msgs_from_viewer_cb,
2510                                                          NULL);
2511                         g_object_unref (G_OBJECT (mail_op));
2512                 } 
2513                 g_object_unref (headers);
2514                 g_object_unref (folder_store);
2515         }
2516         gtk_widget_destroy (dialog);
2517 }
2518
2519 void 
2520 modest_ui_actions_on_move_to (GtkAction *action, 
2521                               ModestWindow *win)
2522 {
2523         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2524                           MODEST_IS_MSG_VIEW_WINDOW (win));
2525
2526         if (MODEST_IS_MAIN_WINDOW (win)) 
2527                 modest_ui_actions_on_main_window_move_to (action, 
2528                                                           MODEST_MAIN_WINDOW (win));
2529         else
2530                 modest_ui_actions_on_msg_view_window_move_to (action, 
2531                                                               MODEST_MSG_VIEW_WINDOW (win));
2532 }
2533
2534 /*
2535  * Calls #HeadersFunc for each header already selected in the main
2536  * window or the message currently being shown in the msg view window
2537  */
2538 static void
2539 do_headers_action (ModestWindow *win, 
2540                    HeadersFunc func,
2541                    gpointer user_data)
2542 {
2543         TnyList *headers_list;
2544         TnyIterator *iter;
2545
2546         /* Get headers */
2547         headers_list = get_selected_headers (win);
2548         if (!headers_list)
2549                 return;
2550
2551         /* Call the function for each header */
2552         iter = tny_list_create_iterator (headers_list);
2553         while (!tny_iterator_is_done (iter)) {
2554                 TnyHeader *header;
2555
2556                 header = TNY_HEADER (tny_iterator_get_current (iter));
2557                 func (header, win, user_data);
2558                 g_object_unref (header);
2559                 tny_iterator_next (iter);
2560         }
2561         g_object_unref (iter);
2562 }
2563
2564 void 
2565 modest_ui_actions_view_attachment (GtkAction *action,
2566                                    ModestWindow *window)
2567 {
2568         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2569                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2570         } else {
2571                 /* not supported window for this action */
2572                 g_return_if_reached ();
2573         }
2574 }
2575
2576 void
2577 modest_ui_actions_save_attachments (GtkAction *action,
2578                                     ModestWindow *window)
2579 {
2580         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2581                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2582         } else {
2583                 /* not supported window for this action */
2584                 g_return_if_reached ();
2585         }
2586 }
2587
2588 void
2589 modest_ui_actions_remove_attachments (GtkAction *action,
2590                                       ModestWindow *window)
2591 {
2592         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2593                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2594         } else {
2595                 /* not supported window for this action */
2596                 g_return_if_reached ();
2597         }
2598 }
2599
2600 void 
2601 modest_ui_actions_on_settings (GtkAction *action, 
2602                                ModestWindow *win)
2603 {
2604         GtkWidget *dialog;
2605
2606         dialog = modest_platform_get_global_settings_dialog ();
2607         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2608         gtk_widget_show (dialog);
2609
2610         gtk_dialog_run (GTK_DIALOG (dialog));
2611
2612         gtk_widget_destroy (dialog);
2613 }