233db19c39416bf21ec3e1456ee02ff31cab5227
[modest] / src / gnome / modest-account-assistant.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 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
32 #include <camel/camel-url.h>
33 #include <widgets/modest-combo-box.h>
34 #include "modest-account-assistant.h"
35 #include "modest-store-widget.h"
36 #include "modest-transport-widget.h"
37 #include "modest-text-utils.h"
38 #include "modest-runtime.h"
39 #include "modest-utils.h"
40 #include "modest-protocol-registry.h"
41 #include "modest-platform.h"
42
43 #include <string.h>
44
45 /* 'private'/'protected' functions */
46 static void       modest_account_assistant_class_init    (ModestAccountAssistantClass *klass);
47 static void       modest_account_assistant_init          (ModestAccountAssistant *obj);
48 static void       modest_account_assistant_finalize      (GObject *obj);
49 static gboolean   on_before_next (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page);
50 static void       on_response (ModestWizardDialog *wizard_dialog,
51                                gint response_id,
52                                gpointer user_data);
53 static void       on_response_before (ModestWizardDialog *wizard_dialog,
54                                       gint response_id,
55                                       gpointer user_data);
56
57 /* list my signals */
58 enum {
59         /* MY_SIGNAL_1, */
60         /* MY_SIGNAL_2, */
61         LAST_SIGNAL
62 };
63
64 typedef struct _ModestAccountAssistantPrivate ModestAccountAssistantPrivate;
65 struct _ModestAccountAssistantPrivate {
66
67         ModestAccountMgr *account_mgr;
68         ModestAccountSettings *settings;
69         gboolean   dirty;
70
71         GtkWidget *notebook;
72
73         GtkWidget *account_name;
74         GtkWidget *fullname;
75         GtkWidget *email;
76        
77         GtkWidget *username;
78         GtkWidget *password;
79         GtkWidget *store_server_widget;
80         GtkWidget *store_protocol_combo;
81         GtkWidget *store_security_combo;
82         GtkWidget *store_secure_auth;
83         GtkWidget *transport_server_widget;
84         GtkWidget *transport_security_combo;
85         GtkWidget *transport_secure_auth_combo;
86         
87         GtkWidget *transport_widget;
88
89         GtkWidget *transport_holder;
90
91         ModestPairList *receiving_transport_store_protos;
92         ModestPairList *sending_transport_store_protos;
93         ModestPairList *security_protos;
94         ModestPairList *transport_security_protos;
95         ModestPairList *transport_auth_protos;
96 };
97
98 #define MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
99                                                       MODEST_TYPE_ACCOUNT_ASSISTANT, \
100                                                       ModestAccountAssistantPrivate))
101 /* globals */
102 static GtkAssistantClass *parent_class = NULL;
103
104 /* uncomment the following if you have defined any signals */
105 /* static guint signals[LAST_SIGNAL] = {0}; */
106
107 static void save_to_settings (ModestAccountAssistant *self);
108
109 GType
110 modest_account_assistant_get_type (void)
111 {
112         static GType my_type = 0;
113         if (!my_type) {
114                 static const GTypeInfo my_info = {
115                         sizeof(ModestAccountAssistantClass),
116                         NULL,           /* base init */
117                         NULL,           /* base finalize */
118                         (GClassInitFunc) modest_account_assistant_class_init,
119                         NULL,           /* class finalize */
120                         NULL,           /* class data */
121                         sizeof(ModestAccountAssistant),
122                         1,              /* n_preallocs */
123                         (GInstanceInitFunc) modest_account_assistant_init,
124                         NULL
125                 };
126                 my_type = g_type_register_static (MODEST_TYPE_WIZARD_DIALOG,
127                                                   "ModestAccountAssistant",
128                                                   &my_info, 0);
129         }
130         return my_type;
131 }
132
133 static void
134 modest_account_assistant_class_init (ModestAccountAssistantClass *klass)
135 {
136         GObjectClass *gobject_class;
137         gobject_class = (GObjectClass*) klass;
138
139         parent_class            = g_type_class_peek_parent (klass);
140         gobject_class->finalize = modest_account_assistant_finalize;
141
142         g_type_class_add_private (gobject_class, sizeof(ModestAccountAssistantPrivate));
143
144         ModestWizardDialogClass *base_klass = (ModestWizardDialogClass*)(klass);
145         base_klass->before_next = on_before_next;
146 }
147
148 static gboolean
149 on_delete_event (GtkWidget *widget,
150                  GdkEvent *event,
151                  ModestAccountAssistant *assistant)
152 {
153         gtk_dialog_response (GTK_DIALOG (assistant), GTK_RESPONSE_CANCEL);
154         return TRUE;
155 }
156
157 static void
158 on_assistant_changed(GtkWidget* widget, ModestAccountAssistant* assistant)
159 {
160         ModestAccountAssistantPrivate* priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(assistant);
161         g_return_if_fail (priv != NULL);
162         priv->dirty = TRUE;
163 }
164
165 static void
166 on_incoming_security_changed(GtkWidget* widget, ModestAccountAssistant* assistant)
167 {
168         ModestAccountAssistantPrivate* priv;
169         ModestProtocolType protocol_id;
170         ModestProtocol *protocol_security_incoming;
171         const gchar *name;
172         ModestProtocolRegistry *registry;
173         gboolean is_secure;
174
175         g_return_if_fail (MODEST_IS_ACCOUNT_ASSISTANT (assistant));
176
177         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(assistant);
178         registry = modest_runtime_get_protocol_registry ();
179         name = (const gchar *) modest_combo_box_get_active_id  (MODEST_COMBO_BOX (priv->store_security_combo));
180         protocol_security_incoming = modest_protocol_registry_get_protocol_by_name (registry, 
181                                                                                     MODEST_PROTOCOL_REGISTRY_SECURE_PROTOCOLS,
182                                                                                     name);
183         protocol_id = modest_protocol_get_type_id (protocol_security_incoming);
184         is_secure = modest_protocol_registry_protocol_type_is_secure (registry, protocol_id);
185
186         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->store_secure_auth), is_secure);
187         gtk_widget_set_sensitive (priv->store_secure_auth, !is_secure);
188         
189         on_assistant_changed (widget, assistant);
190 }
191
192 static void
193 invoke_enable_buttons_vfunc (ModestAccountAssistant *assistant)
194 {
195         ModestWizardDialogClass *klass = MODEST_WIZARD_DIALOG_GET_CLASS (assistant);
196         
197         /* Call the vfunc, which may be overridden by derived classes: */
198         if (klass->enable_buttons) {
199                 GtkNotebook *notebook = NULL;
200                 g_object_get (assistant, "wizard-notebook", &notebook, NULL);
201                 
202                 const gint current_page_num = gtk_notebook_get_current_page (notebook);
203                 if (current_page_num == -1)
204                         return;
205                         
206                 GtkWidget* current_page_widget = gtk_notebook_get_nth_page (notebook, current_page_num);
207                 (*(klass->enable_buttons))(MODEST_WIZARD_DIALOG (assistant), current_page_widget);
208         }
209 }
210
211 static void
212 on_entry_changed (GtkEditable *editable, gpointer userdata)
213 {
214         on_assistant_changed (NULL, MODEST_ACCOUNT_ASSISTANT (userdata));
215         invoke_enable_buttons_vfunc(MODEST_ACCOUNT_ASSISTANT (userdata));
216 }
217
218 static void
219 on_combo_changed (GtkComboBox *combo, gpointer userdata)
220 {
221         on_assistant_changed (NULL, MODEST_ACCOUNT_ASSISTANT (userdata));
222         invoke_enable_buttons_vfunc(MODEST_ACCOUNT_ASSISTANT (userdata));
223 }
224
225 static void
226 add_intro_page (ModestAccountAssistant *assistant)
227 {
228         GtkWidget *page, *label;
229         ModestAccountAssistantPrivate *priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE (assistant);
230         
231         page = gtk_vbox_new (FALSE, 12);
232         
233         label = gtk_label_new (_("mcen_ia_emailsetup_intro"));
234         gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
235         gtk_misc_set_padding (GTK_MISC (label), 12, 12);
236         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
237         gtk_box_pack_start (GTK_BOX(page), label, FALSE, FALSE, 0);
238         gtk_widget_set_size_request (label, 400, -1);
239         gtk_widget_show_all (page);
240         
241         gtk_notebook_append_page (GTK_NOTEBOOK(priv->notebook), page, NULL);
242                 
243         gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(priv->notebook), page,
244                                       _("mcen_ti_emailsetup_welcome"));
245         /* gtk_notebook_set_page_type (GTK_NOTEBOOK(assistant), page, */
246         /*                           GTK_ASSISTANT_PAGE_INTRO); */
247         /* gtk_notebook_set_page_complete (GTK_ASSISTANT(assistant), */
248         /*                               page, TRUE); */
249 }
250
251
252 static void
253 set_current_page_complete (ModestAccountAssistant *self, gboolean complete)
254 {
255         GtkWidget *page;
256         gint pageno;
257         ModestAccountAssistantPrivate *priv;
258
259         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE (self);
260
261         pageno = gtk_notebook_get_current_page (GTK_NOTEBOOK(priv->notebook));
262
263         if (pageno != -1) {
264                 page   = gtk_notebook_get_nth_page (GTK_NOTEBOOK(priv->notebook), pageno);
265                 /* gtk_assistant_set_page_complete (GTK_NOTEBOOK(priv->notebook), page, complete); */
266         }
267 }
268
269
270 static GtkWidget *
271 field_name_label (const gchar *text)
272 {
273         GtkWidget *label;
274         gchar *fixed_text;
275
276         fixed_text = g_strconcat (text, ":", NULL);
277         label = gtk_label_new (fixed_text);
278         g_free (fixed_text);
279         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
280
281         return label;
282 }
283
284 static void
285 add_identity_page (ModestAccountAssistant *self)
286 {
287         GtkWidget *page, *label, *table, *frame;
288         GtkWidget *alignment;
289         ModestAccountAssistantPrivate *priv;
290
291         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
292
293         priv->account_name = gtk_entry_new ();
294         gtk_entry_set_max_length (GTK_ENTRY (priv->account_name), 40);
295         g_signal_connect (G_OBJECT (priv->account_name), "changed", G_CALLBACK (on_entry_changed), self);
296         priv->fullname = gtk_entry_new ();
297         gtk_entry_set_max_length (GTK_ENTRY (priv->fullname), 40);
298         g_signal_connect (G_OBJECT (priv->fullname), "changed", G_CALLBACK (on_entry_changed), self);
299         priv->email    = gtk_entry_new ();
300         gtk_entry_set_width_chars (GTK_ENTRY (priv->email), 40);
301         g_signal_connect (G_OBJECT (priv->email), "changed", G_CALLBACK (on_entry_changed), self);
302         priv->username = gtk_entry_new ();
303         gtk_entry_set_width_chars (GTK_ENTRY (priv->username), 40);
304         g_signal_connect (G_OBJECT (priv->username), "changed", G_CALLBACK (on_entry_changed), self);
305         priv->password = gtk_entry_new ();
306         gtk_entry_set_width_chars (GTK_ENTRY (priv->password), 40);
307         gtk_entry_set_visibility (GTK_ENTRY (priv->password), FALSE);
308         
309         page = gtk_vbox_new (FALSE, 24);
310
311         label = gtk_label_new (
312                 _("Please enter below the name for the account you're creating."));
313         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
314         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
315         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
316         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 12, 12);
317         gtk_container_add (GTK_CONTAINER (alignment), label);
318         gtk_box_pack_start (GTK_BOX(page), alignment, FALSE, FALSE, 0);
319         
320         table = gtk_table_new (1,2, FALSE);
321         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
322         gtk_table_set_row_spacings (GTK_TABLE (table), 1);
323         gtk_table_attach_defaults (GTK_TABLE(table),field_name_label (_("Account name")),
324                                    0,1,0,1);
325         gtk_table_attach_defaults (GTK_TABLE(table),priv->account_name,
326                                    1,2,0,1);
327         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
328         gtk_container_add (GTK_CONTAINER (alignment), table);
329         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 12, 0);
330         gtk_box_pack_start (GTK_BOX(page), alignment, FALSE, FALSE, 0);
331
332         frame = gtk_frame_new (NULL);
333         label = gtk_label_new (NULL);
334         gtk_label_set_markup (GTK_LABEL (label), _("<b>Public information </b>"));
335         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
336         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
337         table = gtk_table_new (2,2, FALSE);
338         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
339         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
340         gtk_table_attach_defaults (GTK_TABLE(table),field_name_label (_("Full name")),
341                                    0,1,0,1);
342         gtk_table_attach_defaults (GTK_TABLE(table),field_name_label (_("Email address")),
343                                    0,1,1,2);
344         gtk_table_attach_defaults (GTK_TABLE(table),priv->fullname,
345                                    1,2,0,1);
346         gtk_table_attach_defaults (GTK_TABLE(table),priv->email,
347                                    1,2,1,2);
348         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
349         gtk_container_add (GTK_CONTAINER (alignment), table);
350         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
351         gtk_container_add (GTK_CONTAINER (frame), alignment);
352         gtk_box_pack_start (GTK_BOX(page), frame, FALSE, FALSE, 0);
353
354
355         frame = gtk_frame_new (NULL);
356         label = gtk_label_new (NULL);
357         gtk_label_set_markup (GTK_LABEL (label), _("<b>Server account </b>"));
358         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
359         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
360         table = gtk_table_new (2,2, FALSE);
361         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
362         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
363         gtk_table_attach_defaults (GTK_TABLE(table),field_name_label (_("User name")),
364                                    0,1,0,1);
365         gtk_table_attach_defaults (GTK_TABLE(table),field_name_label (_("Password")),
366                                    0,1,1,2);
367         gtk_table_attach_defaults (GTK_TABLE(table),priv->username,
368                                    1,2,0,1);
369         gtk_table_attach_defaults (GTK_TABLE(table),priv->password,
370                                    1,2,1,2);
371         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
372         gtk_container_add (GTK_CONTAINER (alignment), table);
373         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
374         gtk_container_add (GTK_CONTAINER (frame), alignment);
375         gtk_box_pack_start (GTK_BOX(page), frame, FALSE, FALSE, 0);
376         
377         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
378         gtk_container_add (GTK_CONTAINER (alignment), page);
379         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 12, 12);
380         gtk_widget_show_all (alignment);
381         gtk_notebook_append_page (GTK_NOTEBOOK(priv->notebook), alignment, NULL);
382         
383         gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(priv->notebook), alignment,
384                                       _("Identity"));
385         /* gtk_assistant_set_page_type (GTK_ASSISTANT(self), alignment, */
386         /*                           GTK_ASSISTANT_PAGE_CONTENT); */
387         /* gtk_assistant_set_page_complete (GTK_ASSISTANT(self), */
388         /*                               alignment, FALSE); */
389 }       
390
391
392 static void
393 receiving_page_update_completeness (GtkEditable *editable,
394                                     ModestAccountAssistant *self)
395 {
396         ModestAccountAssistantPrivate *priv;
397         const gchar *txt;
398
399         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
400
401         txt = gtk_entry_get_text (GTK_ENTRY (priv->store_server_widget));
402         if (!txt || strlen(txt) == 0) {
403                 set_current_page_complete (self, FALSE);
404                 return;
405         }
406         set_current_page_complete (self, TRUE);
407 }
408
409 static void
410 add_receiving_page (ModestAccountAssistant *self)
411 {
412         GtkWidget *page, *vbox;
413         GtkWidget *table, *frame;
414         GtkWidget *alignment;
415         ModestAccountAssistantPrivate *priv;
416         GtkWidget *label;
417
418         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
419         page = gtk_alignment_new (0.5, 0.0, 1.0, 0.0);
420         gtk_alignment_set_padding (GTK_ALIGNMENT (page), 12, 12, 12, 12);
421         vbox = gtk_vbox_new (FALSE, 24);
422         gtk_container_add (GTK_CONTAINER (page), vbox);
423
424         /* Warning label on top */
425         label = gtk_label_new (_("Setting details for the incoming mail server."));
426         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
427         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
428         gtk_box_pack_start (GTK_BOX(vbox),
429                             label,
430                             FALSE, FALSE, 0);
431
432         /* Note: This ModestPairList* must exist for as long as the combo
433          * that uses it, because the ModestComboBox uses the ID opaquely, 
434          * so it can't know how to manage its memory. */
435         priv->receiving_transport_store_protos = 
436                 modest_protocol_info_get_supported_store_protocol_pair_list ();
437         priv->store_protocol_combo = modest_combo_box_new (priv->receiving_transport_store_protos, g_str_equal);
438         priv->store_server_widget = gtk_entry_new ();
439
440         /* Setup incoming server frame */
441         frame = gtk_frame_new (NULL);
442         label = gtk_label_new (NULL);
443         gtk_label_set_markup (GTK_LABEL (label), _("<b>Incoming server</b>"));
444         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
445         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
446         table = gtk_table_new (2, 2, FALSE);
447         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
448         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
449         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Account type")),
450                           0, 1, 0, 1,
451                           GTK_FILL, 0, 0, 0);
452         alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
453         gtk_container_add (GTK_CONTAINER (alignment), priv->store_protocol_combo);
454         gtk_table_attach (GTK_TABLE (table), alignment,
455                           1, 2, 0, 1,
456                           GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
457         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Incoming server")),
458                           0, 1, 1, 2,
459                           GTK_FILL, GTK_FILL, 0, 0);
460         gtk_table_attach (GTK_TABLE (table), priv->store_server_widget,
461                           1, 2, 1, 2,
462                           GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
463         alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
464         gtk_container_add (GTK_CONTAINER (alignment), table);
465         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
466         gtk_container_add (GTK_CONTAINER (frame), alignment);
467         gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
468
469         /* Setup security information widgets */
470         priv->security_protos = 
471                 modest_protocol_info_get_connection_protocol_pair_list ();
472         priv->store_security_combo = modest_combo_box_new (priv->security_protos, g_str_equal);
473         priv->store_secure_auth = gtk_check_button_new ();
474
475         /* Setup security frame */
476         frame = gtk_frame_new (NULL);
477         label = gtk_label_new (NULL);
478         gtk_label_set_markup (GTK_LABEL (label), _("<b>Security options</b>"));
479         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
480         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
481         table = gtk_table_new (2, 2, FALSE);
482         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
483         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
484         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Secure connection")),
485                           0, 1, 0, 1,
486                           GTK_FILL, 0, 0, 0);
487         gtk_table_attach (GTK_TABLE (table), priv->store_security_combo,
488                           1, 2, 0, 1,
489                           GTK_FILL | GTK_EXPAND, 0, 0, 0);
490         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Use secure authentication")),
491                           0, 1, 1, 2,
492                           GTK_FILL, GTK_FILL, 0, 0);
493         gtk_table_attach_defaults (GTK_TABLE (table), priv->store_secure_auth,
494                                    1, 2, 1, 2);
495         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
496         gtk_container_add (GTK_CONTAINER (alignment), table);
497         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
498         gtk_container_add (GTK_CONTAINER (frame), alignment);
499         gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, FALSE, 0);
500         
501         /* Setup assistant page */
502         gtk_notebook_append_page (GTK_NOTEBOOK(priv->notebook), page, NULL);
503                 
504         gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(priv->notebook), page,
505                                          _("Incoming details"));
506         gtk_widget_show_all (page);
507 }
508
509
510
511
512 static void
513 on_sending_combo_box_changed (GtkComboBox *combo, ModestAccountAssistant *self)
514 {
515         ModestAccountAssistantPrivate *priv;
516         gchar *chosen;
517         ModestProtocol *proto;
518
519         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
520
521         chosen = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo));
522
523         if (priv->transport_widget)
524                 gtk_container_remove (GTK_CONTAINER(priv->transport_holder),
525                                       priv->transport_widget);
526
527         proto = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
528                                                                MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
529                                                                chosen);
530         priv->transport_widget = modest_transport_widget_new (modest_protocol_get_type_id (proto));
531
532         gtk_container_add (GTK_CONTAINER(priv->transport_holder),
533                            priv->transport_widget);
534
535         gtk_widget_show_all (priv->transport_holder);
536         on_assistant_changed (NULL, MODEST_ACCOUNT_ASSISTANT (self));
537 }
538
539
540
541 static void
542 add_sending_page (ModestAccountAssistant *self)
543 {
544         GtkWidget *page, *vbox;
545         GtkWidget *table, *frame;
546         GtkWidget *alignment;
547         ModestAccountAssistantPrivate *priv;
548         GtkWidget *label;
549
550         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
551         page = gtk_alignment_new (0.5, 0.0, 1.0, 0.0);
552         gtk_alignment_set_padding (GTK_ALIGNMENT (page), 12, 12, 12, 12);
553         vbox = gtk_vbox_new (FALSE, 24);
554         gtk_container_add (GTK_CONTAINER (page), vbox);
555
556         /* Warning label on top */
557         label = gtk_label_new (_("Settings for the outgoing mail server"));
558         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
559         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
560         gtk_box_pack_start (GTK_BOX(vbox),
561                             label,
562                             FALSE, FALSE, 0);
563
564         priv->transport_server_widget = gtk_entry_new ();
565         /* Setup incoming server frame */
566         frame = gtk_frame_new (NULL);
567         label = gtk_label_new (NULL);
568         gtk_label_set_markup (GTK_LABEL (label), _("<b>Outgoing server</b>"));
569         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
570         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
571         table = gtk_table_new (2, 2, FALSE);
572         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
573         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
574         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Outgoing server (SMTP)")),
575                           0, 1, 0, 1,
576                           GTK_FILL, GTK_FILL, 0, 0);
577         gtk_table_attach (GTK_TABLE (table), priv->transport_server_widget,
578                           1, 2, 0, 1,
579                           GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
580         alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
581         gtk_container_add (GTK_CONTAINER (alignment), table);
582         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
583         gtk_container_add (GTK_CONTAINER (frame), alignment);
584         gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
585
586         /* Setup security information widgets */
587         priv->transport_security_protos = 
588                 modest_protocol_info_get_connection_protocol_pair_list ();
589         priv->transport_security_combo = modest_combo_box_new (priv->security_protos, g_str_equal);
590         priv->transport_auth_protos = modest_protocol_info_get_auth_protocol_pair_list ();
591         priv->transport_secure_auth_combo = GTK_WIDGET (modest_combo_box_new (priv->transport_auth_protos, g_str_equal));
592
593         /* Setup security frame */
594         frame = gtk_frame_new (NULL);
595         label = gtk_label_new (NULL);
596         gtk_label_set_markup (GTK_LABEL (label), _("<b>Security options</b>"));
597         gtk_frame_set_label_widget (GTK_FRAME (frame), label);
598         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
599         table = gtk_table_new (2, 2, FALSE);
600         gtk_table_set_col_spacings (GTK_TABLE (table), 6);
601         gtk_table_set_row_spacings (GTK_TABLE (table), 3);
602         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Secure connection")),
603                           0, 1, 0, 1,
604                           GTK_FILL, 0, 0, 0);
605         gtk_table_attach (GTK_TABLE (table), priv->transport_security_combo,
606                           1, 2, 0, 1,
607                           GTK_FILL | GTK_EXPAND, 0, 0, 0);
608         gtk_table_attach (GTK_TABLE (table), field_name_label (_("Secure authentication")),
609                           0, 1, 1, 2,
610                           GTK_FILL, GTK_FILL, 0, 0);
611         gtk_table_attach_defaults (GTK_TABLE (table), priv->transport_secure_auth_combo,
612                                    1, 2, 1, 2);
613         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
614         gtk_container_add (GTK_CONTAINER (alignment), table);
615         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
616         gtk_container_add (GTK_CONTAINER (frame), alignment);
617         gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, FALSE, 0);
618         
619         /* Setup assistant page */
620         gtk_notebook_append_page (GTK_NOTEBOOK(priv->notebook), page, NULL);
621                 
622         gtk_notebook_set_tab_label_text (GTK_NOTEBOOK(priv->notebook), page,
623                                          _("Outgoing details"));
624         gtk_widget_show_all (page);
625
626 }
627
628 static void
629 modest_account_assistant_init (ModestAccountAssistant *obj)
630 {       
631         ModestAccountAssistantPrivate *priv;    
632         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(obj);       
633
634         priv->account_mgr       = NULL;
635
636         priv->store_server_widget       = NULL;
637         priv->transport_widget  = NULL;
638         priv->settings = modest_account_settings_new ();
639         priv->dirty = FALSE;
640
641         priv->notebook = gtk_notebook_new ();
642         gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
643
644         g_object_set (obj, "wizard-notebook", priv->notebook, NULL);
645         g_object_set (obj, "wizard-name", _("Account wizard"), NULL);
646
647         add_intro_page (obj);
648         add_identity_page (obj); 
649         add_receiving_page (obj); 
650         add_sending_page (obj);
651
652         gtk_notebook_set_current_page (GTK_NOTEBOOK(priv->notebook), 0);
653         gtk_window_set_resizable (GTK_WINDOW(obj), TRUE);       
654         gtk_window_set_default_size (GTK_WINDOW(obj), 400, 400);
655         
656         gtk_window_set_modal (GTK_WINDOW(obj), TRUE);
657
658         g_signal_connect_after (G_OBJECT (obj), "response",
659                                 G_CALLBACK (on_response), obj);
660
661         /* This is to show a confirmation dialog when the user hits cancel */
662         g_signal_connect (G_OBJECT (obj), "response",
663                           G_CALLBACK (on_response_before), obj);
664
665         g_signal_connect (G_OBJECT (obj), "delete-event",
666                           G_CALLBACK (on_delete_event), obj);
667 }
668
669 static void
670 modest_account_assistant_finalize (GObject *obj)
671 {
672         ModestAccountAssistantPrivate *priv;
673                 
674         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(obj);
675         
676         if (priv->account_mgr) {
677                 g_object_unref (G_OBJECT(priv->account_mgr));
678                 priv->account_mgr = NULL;
679         }
680
681         if (priv->settings) {
682                 g_object_unref (G_OBJECT (priv->settings));
683                 priv->settings = NULL;
684         }
685         
686         /* These had to stay alive for as long as the comboboxes that used them: */
687         modest_pair_list_free (priv->receiving_transport_store_protos);
688         modest_pair_list_free (priv->sending_transport_store_protos);
689
690         G_OBJECT_CLASS(parent_class)->finalize (obj);
691 }
692
693 static const gchar*
694 get_account_name (ModestAccountAssistant *self)
695 {
696         ModestAccountAssistantPrivate *priv;
697         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
698
699         return gtk_entry_get_text (GTK_ENTRY(priv->account_name));
700 }
701
702 static const gchar*
703 get_fullname (ModestAccountAssistant *self)
704 {
705         ModestAccountAssistantPrivate *priv;
706         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
707
708         return gtk_entry_get_text (GTK_ENTRY(priv->fullname));
709 }
710
711
712
713 static const gchar*
714 get_email (ModestAccountAssistant *self)
715 {
716         ModestAccountAssistantPrivate *priv;
717         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
718
719         return gtk_entry_get_text (GTK_ENTRY(priv->email));
720 }
721
722
723
724 /*
725  * FIXME: hmmmm this a Camel internal thing, should move this
726  * somewhere else
727  */
728 static gchar*
729 get_account_uri (ModestProtocolType proto, const gchar* path)
730 {
731         CamelURL *url;
732         gchar *uri;
733         
734         if (proto == modest_protocol_registry_get_mbox_type_id ()) {
735                 url = camel_url_new ("mbox:", NULL);
736         } else {
737                 if (proto == modest_protocol_registry_get_maildir_type_id ())
738                         url = camel_url_new ("maildir:", NULL);
739                 else
740                         g_return_val_if_reached (NULL);
741         }
742
743         camel_url_set_path (url, path);
744         uri = camel_url_to_string (url, 0);
745         camel_url_free (url);
746
747         return uri;     
748 }
749
750 static gchar*
751 get_new_server_account_name (ModestAccountMgr* acc_mgr, 
752                              ModestProtocolType proto_id,
753                              const gchar *username, 
754                              const gchar *servername)
755 {
756         gchar *name;
757         const gchar *proto_name;
758         gint  i = 0;
759         ModestProtocolRegistry *registry;
760         ModestProtocol *proto;
761
762         registry = modest_runtime_get_protocol_registry ();
763         proto = modest_protocol_registry_get_protocol_by_type (registry, proto_id);
764         proto_name = modest_protocol_get_name (proto);
765
766         while (TRUE) {
767                 name = g_strdup_printf ("%s:%d", proto_name, i++);
768
769                 if (modest_account_mgr_account_exists (acc_mgr, name, TRUE))
770                         g_free (name);
771                 else
772                         break;
773         }
774         return name;
775 }
776
777
778
779 GtkWidget*
780 modest_account_assistant_new (ModestAccountMgr *account_mgr)
781 {
782         GObject *obj;
783         ModestAccountAssistant *self;
784         ModestAccountAssistantPrivate *priv;
785
786         g_return_val_if_fail (account_mgr, NULL);
787         
788         obj  = g_object_new(MODEST_TYPE_ACCOUNT_ASSISTANT, NULL);
789         self = MODEST_ACCOUNT_ASSISTANT(obj);
790
791         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
792
793         g_object_ref (account_mgr);
794         priv->account_mgr = account_mgr;
795
796         return GTK_WIDGET(self);
797 }
798
799 static gchar*
800 get_entered_account_title (ModestAccountAssistant *self)
801 {
802         ModestAccountAssistantPrivate *priv;
803         const gchar* account_title;
804
805         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
806         account_title = gtk_entry_get_text (GTK_ENTRY (priv->account_name));
807
808         if (!account_title || (strlen (account_title) == 0)) {
809                 return NULL;
810         } else {
811                 /* Strip it of whitespace at the start and end: */
812                 gchar *result = g_strdup (account_title);
813                 result = g_strstrip (result);
814                 
815                 if (!result)
816                         return NULL;
817                         
818                 if (strlen (result) == 0) {
819                         g_free (result);
820                         return NULL;    
821                 }
822                 
823                 return result;
824         }
825 }
826
827 static gboolean
828 on_before_next (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page)
829 {
830         ModestAccountAssistant *self = MODEST_ACCOUNT_ASSISTANT (dialog);
831         ModestAccountAssistantPrivate *priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE (self);
832
833         /* Do extra validation that couldn't be done for every key press,
834          * either because it was too slow,
835          * or because it requires interaction:
836          */
837         if(!next_page) /* This is NULL when this is a click on Finish. */
838         {
839                 save_to_settings (self);
840                 modest_account_mgr_add_account_from_settings (modest_runtime_get_account_mgr (), priv->settings);
841         }
842         
843         
844         return TRUE;
845 }
846
847 static gint 
848 get_serverport_incoming(ModestProtocolType protocol,
849                         ModestProtocolType security)
850 {
851         int serverport_incoming = 0;
852
853         /* We don't check for SMTP here as that is impossible for an incoming server. */
854         if ((security == modest_protocol_registry_get_none_connection_type_id ()) ||
855             (security == modest_protocol_registry_get_tls_connection_type_id ()) ||
856             (security == modest_protocol_registry_get_tlsop_connection_type_id ())) {
857
858                 if (protocol == MODEST_PROTOCOLS_STORE_IMAP) {
859                         serverport_incoming = 143;
860                 } else if (protocol == MODEST_PROTOCOLS_STORE_POP) {
861                         serverport_incoming = 110;
862                 }
863         } else if (security == modest_protocol_registry_get_ssl_connection_type_id ()) {
864                 if (protocol == MODEST_PROTOCOLS_STORE_IMAP) {
865                         serverport_incoming = 993;
866                 } else if  (protocol == MODEST_PROTOCOLS_STORE_POP) {
867                         serverport_incoming = 995;
868                 }
869         }
870
871         return serverport_incoming;
872 }
873
874 static GList* 
875 check_for_supported_auth_methods (ModestAccountAssistant* self)
876 {
877         GError *error = NULL;
878         ModestProtocolType protocol;
879         const gchar* hostname;
880         const gchar* username;
881         gchar *store_protocol_name, *store_security_name;
882         ModestProtocolType security_protocol;
883         int port_num; 
884         GList *list_auth_methods;
885         ModestAccountAssistantPrivate *priv;
886         
887         priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE (self);
888         hostname = gtk_entry_get_text(GTK_ENTRY(priv->store_server_widget));
889         username = gtk_entry_get_text(GTK_ENTRY(priv->username));
890         store_protocol_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (priv->store_protocol_combo));
891         protocol = modest_protocol_info_get_transport_store_protocol (store_protocol_name);
892         g_free (store_protocol_name);
893         store_security_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (priv->store_security_combo));
894         security_protocol = modest_protocol_info_get_connection_protocol (store_security_name);
895         g_free (store_security_name);
896         port_num = get_serverport_incoming(protocol, security_protocol); 
897         list_auth_methods = modest_utils_get_supported_secure_authentication_methods (protocol, hostname, port_num, 
898                                                                                       username, GTK_WINDOW (self), &error);
899
900         if (list_auth_methods) {
901                 /* TODO: Select the correct method */
902                 GList* list = NULL;
903                 GList* method;
904                 for (method = list_auth_methods; method != NULL; method = g_list_next(method)) {
905                         ModestProtocolType auth = (ModestProtocolType) (GPOINTER_TO_INT(method->data));
906                         if (modest_protocol_info_auth_is_secure(auth)) {
907                                 list = g_list_append(list, GINT_TO_POINTER(auth));
908                         }
909                 }
910
911                 g_list_free(list_auth_methods);
912
913                 if (list)
914                         return list;
915         }
916
917         if(error != NULL)
918                 g_error_free(error);
919
920         return NULL;
921 }
922
923 static ModestProtocolType check_first_supported_auth_method(ModestAccountAssistant* self)
924 {
925         ModestProtocolType result = MODEST_PROTOCOLS_AUTH_PASSWORD;
926
927         GList* methods = check_for_supported_auth_methods(self);
928         if (methods)
929         {
930                 /* Use the first one: */
931                 result = (ModestProtocolType) (GPOINTER_TO_INT(methods->data));
932                 g_list_free(methods);
933         }
934
935         return result;
936 }
937
938 /**
939  * save_to_settings:
940  * @self: a #ModestEasysetupWizardDialog
941  *
942  * takes information from all the wizard and stores it in settings
943  */
944 static void
945 save_to_settings (ModestAccountAssistant *self)
946 {
947         ModestAccountAssistantPrivate *priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE (self);
948         gchar* display_name;
949         const gchar *username, *password;
950         gchar *store_hostname, *transport_hostname;
951         guint store_port, transport_port;
952         ModestProtocolType store_protocol, transport_protocol;
953         ModestProtocolType store_security, transport_security;
954         ModestProtocolType store_auth_protocol, transport_auth_protocol;
955         ModestServerAccountSettings *store_settings, *transport_settings;
956         const gchar *fullname, *email_address;
957
958         /* username and password (for both incoming and outgoing): */
959         username = gtk_entry_get_text (GTK_ENTRY (priv->username));
960         password = gtk_entry_get_text (GTK_ENTRY (priv->password));
961
962         /* Incoming server: */
963         /* Note: We need something as default for the ModestTransportStoreProtocol* values, 
964          * or modest_account_mgr_add_server_account will fail. */
965         store_port = 0;
966         store_protocol = MODEST_PROTOCOLS_STORE_POP;
967         store_security = MODEST_PROTOCOLS_CONNECTION_NONE;
968         store_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
969
970         /* Use custom pages because no preset was specified: */
971         store_hostname = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->store_server_widget) ));                
972         store_protocol = modest_protocol_info_get_transport_store_protocol (modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->store_protocol_combo)));
973         store_security = modest_protocol_info_get_connection_protocol (modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->store_security_combo)));
974
975         /* The UI spec says: 
976          * If secure authentication is unchecked, allow sending username and password also as plain text.
977          * If secure authentication is checked, require one of the secure methods during 
978          * connection: SSL, TLS, CRAM-MD5 etc. */
979         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->store_secure_auth)) &&
980             !modest_protocol_registry_protocol_type_is_secure(modest_runtime_get_protocol_registry (),
981                                                               store_security)) {
982                 store_auth_protocol = check_first_supported_auth_method (self);
983         } else {
984                 store_auth_protocol = MODEST_PROTOCOLS_AUTH_PASSWORD;
985         }
986
987         /* now we store the store account settings */
988         store_settings = modest_account_settings_get_store_settings (priv->settings);
989         modest_server_account_settings_set_hostname (store_settings, store_hostname);
990         modest_server_account_settings_set_username (store_settings, username);
991         modest_server_account_settings_set_password (store_settings, password);
992         modest_server_account_settings_set_protocol (store_settings, store_protocol);
993         modest_server_account_settings_set_security (store_settings, store_security);
994         modest_server_account_settings_set_auth_protocol (store_settings, store_auth_protocol);
995         if (store_port != 0)
996                 modest_server_account_settings_set_port (store_settings, store_port);
997
998         g_object_unref (store_settings);
999         g_free (store_hostname);
1000         
1001         /* Outgoing server: */
1002         transport_hostname = NULL;
1003         transport_protocol = MODEST_PROTOCOLS_STORE_POP;
1004         transport_security = MODEST_PROTOCOLS_CONNECTION_NONE;
1005         transport_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
1006         transport_port = 0;
1007         
1008         transport_hostname = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->transport_server_widget) ));
1009         transport_protocol = MODEST_PROTOCOLS_TRANSPORT_SMTP; /* It's always SMTP for outgoing. */
1010         transport_security = modest_protocol_info_get_connection_protocol (modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->transport_security_combo)));
1011         transport_auth_protocol = modest_protocol_info_get_auth_protocol (modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->transport_secure_auth_combo)));
1012             
1013         /* now we transport the transport account settings */
1014         transport_settings = modest_account_settings_get_transport_settings (priv->settings);
1015         modest_server_account_settings_set_hostname (transport_settings, transport_hostname);
1016         modest_server_account_settings_set_username (transport_settings, username);
1017         modest_server_account_settings_set_password (transport_settings, password);
1018         modest_server_account_settings_set_protocol (transport_settings, transport_protocol);
1019         modest_server_account_settings_set_security (transport_settings, transport_security);
1020         modest_server_account_settings_set_auth_protocol (transport_settings, transport_auth_protocol);
1021         if (transport_port != 0)
1022                 modest_server_account_settings_set_port (transport_settings, transport_port);
1023
1024         g_object_unref (transport_settings);
1025         g_free (transport_hostname);
1026         
1027         fullname = gtk_entry_get_text (GTK_ENTRY (priv->fullname));
1028         email_address = gtk_entry_get_text (GTK_ENTRY (priv->email));
1029         modest_account_settings_set_fullname (priv->settings, fullname);
1030         modest_account_settings_set_email_address (priv->settings, email_address);
1031         /* we don't set retrieve type to preserve advanced settings if any. By default account settings
1032            are set to headers only */
1033         
1034         display_name = get_entered_account_title (self);
1035         modest_account_settings_set_display_name (priv->settings, display_name);
1036         g_free (display_name);
1037
1038 }
1039
1040 static void 
1041 on_response (ModestWizardDialog *wizard_dialog,
1042              gint response_id,
1043              gpointer user_data)
1044 {
1045         ModestAccountAssistant *self = MODEST_ACCOUNT_ASSISTANT (wizard_dialog);
1046
1047         invoke_enable_buttons_vfunc (self);
1048 }
1049
1050 static void 
1051 on_response_before (ModestWizardDialog *wizard_dialog,
1052                     gint response_id,
1053                     gpointer user_data)
1054 {
1055         ModestAccountAssistant *self = MODEST_ACCOUNT_ASSISTANT (wizard_dialog);
1056         ModestAccountAssistantPrivate *priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(wizard_dialog);
1057
1058         if (response_id == GTK_RESPONSE_CANCEL) {
1059                 /* This is mostly copied from
1060                  * src/maemo/modest-account-settings-dialog.c */
1061                 if (priv->dirty) {
1062                         gint dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
1063                                                                                         _("imum_nc_wizard_confirm_lose_changes"));
1064
1065                         if (dialog_response != GTK_RESPONSE_OK) {
1066                                 /* Don't let the dialog close */
1067                                 g_signal_stop_emission_by_name (wizard_dialog, "response");
1068                         }
1069                 }
1070         }
1071 }
1072