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