39c0ff20f4eac86736db2a80c5ff5de5cee15548
[modest] / src / hildon2 / modest-easysetup-wizard-dialog.c
1
2 /* Copyright (c) 2006, Nokia Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  * * Neither the name of the Nokia Corporation nor the names of its
15  *   contributors may be used to endorse or promote products derived from
16  *   this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30  
31 #include <config.h>
32 #include "modest-easysetup-wizard-dialog.h"
33 #include <glib/gi18n.h>
34 #include <gtk/gtknotebook.h>
35 #include <gtk/gtkvbox.h>
36 #include <gtk/gtklabel.h>
37 #include <gtk/gtkentry.h>
38 #include <gtk/gtkbutton.h>
39 #include <gtk/gtkcheckbutton.h>
40 #include <gtk/gtkmessagedialog.h>
41 #include <gtk/gtkseparator.h>
42 #include "modest-country-picker.h"
43 #include "modest-provider-picker.h"
44 #include "modest-servertype-picker.h"
45 #include "widgets/modest-validating-entry.h"
46 #include "modest-text-utils.h"
47 #include "modest-conf.h"
48 #include "modest-defs.h"
49 #include "modest-account-mgr.h"
50 #include "modest-signal-mgr.h"
51 #include "modest-account-mgr-helpers.h"
52 #include "modest-runtime.h" /* For modest_runtime_get_account_mgr(). */
53 #include "modest-connection-specific-smtp-window.h"
54 #include "widgets/modest-ui-constants.h"
55 #include "widgets/modest-default-account-settings-dialog.h"
56 #include "widgets/modest-easysetup-wizard-page.h"
57 #include "modest-maemo-utils.h"
58 #include "modest-utils.h"
59 #include "modest-hildon-includes.h"
60 #include "modest-maemo-security-options-view.h"
61 #include "modest-account-protocol.h"
62
63 /* Include config.h so that _() works: */
64 #ifdef HAVE_CONFIG_H
65 #include <config.h>
66 #endif
67
68 G_DEFINE_TYPE (ModestEasysetupWizardDialog, modest_easysetup_wizard_dialog, MODEST_TYPE_WIZARD_DIALOG);
69
70 #define MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
71                                                     MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, \
72                                                     ModestEasysetupWizardDialogPrivate))
73
74 #define LABELS_WIDTH 480
75 #define DIALOG_WIDTH LABELS_WIDTH + MODEST_MARGIN_DOUBLE
76
77 typedef struct _ModestEasysetupWizardDialogPrivate ModestEasysetupWizardDialogPrivate;
78
79
80 typedef enum {
81         MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED = 0x01,
82         MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED = 0x02
83 } ModestEasysetupWizardDialogServerChanges;
84
85 struct _ModestEasysetupWizardDialogPrivate
86 {
87         ModestPresets *presets;
88
89         /* Remember what fields the user edited manually to not prefill them
90          * again. */
91         ModestEasysetupWizardDialogServerChanges server_changes;
92         
93         /* Check if the user changes a field to show a confirmation dialog */
94         gboolean dirty;
95
96         /* If we have a pending load of settings or not. */
97         gboolean pending_load_settings;
98         
99         /* Used by derived widgets to query existing accounts,
100          * and to create new accounts: */
101         ModestAccountMgr *account_manager;
102         ModestAccountSettings *settings;
103         
104         /* notebook pages: */
105         GtkWidget *page_welcome;
106         GtkWidget *check_support_progress;
107         gboolean  check_support_done;
108         guint check_support_show_progress_id;
109         guint check_support_progress_pulse_id;
110         gint pending_check_support;
111         gboolean destroyed;
112         
113         GtkWidget *page_account_details;
114         GtkWidget *account_country_picker;
115         GtkWidget *account_serviceprovider_picker;
116         GtkWidget *entry_account_title;
117         GtkWidget *caption_account_title;
118         
119         GtkWidget *page_user_details;
120         GtkWidget *entry_user_name;
121         GtkWidget *entry_user_username;
122         GtkWidget *entry_user_password;
123         GtkWidget *entry_user_email;
124         
125         GtkWidget *page_complete_easysetup;
126         
127         GtkWidget *page_custom_incoming;
128         GtkWidget *incoming_servertype_picker;
129         GtkWidget *caption_incoming;
130         GtkWidget *entry_incomingserver;
131
132         /* Security widgets */
133         GtkWidget *incoming_security;
134         GtkWidget *outgoing_security;
135
136         GtkWidget *page_custom_outgoing;
137         GtkWidget *entry_outgoingserver;
138         GtkWidget *checkbox_outgoing_smtp_specific;
139         GtkWidget *button_outgoing_smtp_servers;
140         
141         GtkWidget *page_complete_customsetup;
142
143         ModestProtocolType last_plugin_protocol_selected;
144         GSList *missing_data_signals;
145 };
146
147 static void save_to_settings (ModestEasysetupWizardDialog *self);
148 static void real_enable_buttons (ModestWizardDialog *dialog, gboolean enable_next);
149 static void on_update_model (ModestWizardDialog *dialog);
150 static gboolean on_save (ModestWizardDialog *dialog);
151 static GList* check_for_supported_auth_methods (ModestEasysetupWizardDialog* self);
152 static gboolean check_has_supported_auth_methods(ModestEasysetupWizardDialog* self);
153 static void check_support_callback (ModestAccountProtocol *protocol,
154                                     gboolean supported,
155                                     gpointer userdata);
156 static void check_support_of_protocols (ModestEasysetupWizardDialog *self);
157 static gboolean check_support_show_progress (gpointer userdata);
158 static gboolean check_support_progress_pulse (gpointer userdata);
159
160 static gboolean
161 on_delete_event (GtkWidget *widget,
162                  GdkEvent *event,
163                  ModestEasysetupWizardDialog *wizard)
164 {
165         gtk_dialog_response (GTK_DIALOG (wizard), GTK_RESPONSE_CANCEL);
166         return TRUE;
167 }
168
169 static void
170 on_easysetup_changed(GtkWidget* widget, ModestEasysetupWizardDialog* wizard)
171 {
172         ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(wizard);
173         g_return_if_fail (priv != NULL);
174         priv->dirty = TRUE;
175 }
176
177 static void
178 modest_easysetup_wizard_dialog_dispose (GObject *object)
179 {
180         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (object);
181         priv->destroyed = TRUE;
182
183         if (priv->check_support_show_progress_id > 0) {
184                 g_source_remove (priv->check_support_show_progress_id);
185                 priv->check_support_show_progress_id = 0;
186         }
187
188         if (priv->check_support_progress_pulse_id > 0) {
189                 g_source_remove (priv->check_support_progress_pulse_id);
190                 priv->check_support_progress_pulse_id = 0;
191         }
192
193         if (G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->dispose)
194                 G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->dispose (object);
195 }
196
197 static void
198 modest_easysetup_wizard_dialog_finalize (GObject *object)
199 {
200         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (object);
201         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
202
203         if (priv->account_manager)
204                 g_object_unref (G_OBJECT (priv->account_manager));
205
206         if (priv->presets)
207                 modest_presets_destroy (priv->presets);
208
209         if (priv->settings)
210                 g_object_unref (priv->settings);
211
212         if (priv->missing_data_signals) {
213                 modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
214                 priv->missing_data_signals = NULL;
215         }
216
217         G_OBJECT_CLASS (modest_easysetup_wizard_dialog_parent_class)->finalize (object);
218 }
219
220 static void
221 create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self);
222
223 static void
224 set_default_custom_servernames(ModestEasysetupWizardDialog *dialog);
225
226 static void on_servertype_selector_changed(HildonTouchSelector *selector, gint column, gpointer user_data);
227
228 static gint 
229 get_port_from_protocol (ModestProtocolType server_type,
230                         gboolean alternate_port)
231 {
232         int server_port = 0;
233         ModestProtocol *protocol;
234         ModestProtocolRegistry *protocol_registry;
235
236         protocol_registry = modest_runtime_get_protocol_registry ();
237         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, server_type);
238
239         if (alternate_port) {
240                 server_port = modest_account_protocol_get_alternate_port (MODEST_ACCOUNT_PROTOCOL (protocol));
241         } else {
242                 server_port = modest_account_protocol_get_port (MODEST_ACCOUNT_PROTOCOL (protocol));
243         }
244         return server_port;
245 }
246
247 static void
248 invoke_enable_buttons_vfunc (ModestEasysetupWizardDialog *wizard_dialog)
249 {
250         ModestWizardDialogClass *klass = MODEST_WIZARD_DIALOG_GET_CLASS (wizard_dialog);
251
252         /* Call the vfunc, which may be overridden by derived classes: */
253         if (klass->enable_buttons) {
254                 GtkNotebook *notebook = NULL;
255                 g_object_get (wizard_dialog, "wizard-notebook", &notebook, NULL);
256
257                 const gint current_page_num = gtk_notebook_get_current_page (notebook);
258                 if (current_page_num == -1)
259                         return;
260
261                 GtkWidget* current_page_widget = gtk_notebook_get_nth_page (notebook, current_page_num);
262                 (*(klass->enable_buttons))(MODEST_WIZARD_DIALOG (wizard_dialog), current_page_widget);
263         }
264 }
265
266 static void
267 on_caption_entry_changed (GtkEditable *editable, gpointer user_data)
268 {
269         ModestEasysetupWizardDialog *self;
270
271         g_return_if_fail (user_data);
272
273         self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
274
275         invoke_enable_buttons_vfunc(self);
276 }
277
278 static void
279 on_caption_combobox_changed (GtkComboBox *widget, gpointer user_data)
280 {
281         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
282         g_assert(self);
283         invoke_enable_buttons_vfunc(self);
284 }
285
286 static void
287 on_picker_button_value_changed (HildonPickerButton *widget, gpointer user_data)
288 {
289         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
290         g_assert(self);
291         invoke_enable_buttons_vfunc(self);
292 }
293
294 static void
295 on_serviceprovider_picker_button_value_changed (HildonPickerButton *widget, gpointer user_data)
296 {
297         gchar* default_account_name_start;
298         gchar* default_account_name;
299         ModestEasysetupWizardDialog *self;
300         ModestEasysetupWizardDialogPrivate *priv;
301         ModestProviderPickerIdType provider_id_type;
302         ModestProtocol *protocol;
303         gchar *proto_name;
304         ModestProtocolType proto_type;
305         gboolean hide_account_title;
306
307         self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
308         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
309
310         on_picker_button_value_changed (widget, user_data);
311
312         provider_id_type = modest_provider_picker_get_active_id_type (
313                 MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker));
314         if (provider_id_type == MODEST_PROVIDER_PICKER_ID_OTHER) {
315                 default_account_name_start = g_strdup (_("mcen_ia_emailsetup_defaultname"));
316         } else {
317                 GtkWidget *selector;
318
319                 selector = GTK_WIDGET (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (widget)));
320                 default_account_name_start = 
321                         g_strdup (hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)));
322                 
323         }
324         default_account_name = modest_account_mgr_get_unused_account_display_name (
325                 priv->account_manager, default_account_name_start);
326         g_free (default_account_name_start);
327         default_account_name_start = NULL;
328
329         hide_account_title = FALSE;
330         proto_name = modest_provider_picker_get_active_provider_id (MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker));
331         if (proto_name != NULL) {
332                 protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
333                                                                           MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS,
334                                                                           proto_name);
335                 if (protocol != NULL) {
336                         proto_type = modest_protocol_get_type_id (protocol);
337                         
338                         hide_account_title = (modest_protocol_registry_protocol_type_has_tag 
339                                               (modest_runtime_get_protocol_registry (),
340                                                proto_type,
341                                                MODEST_PROTOCOL_REGISTRY_SINGLETON_PROVIDER_PROTOCOLS) ||
342                                               modest_protocol_registry_protocol_type_has_tag
343                                               (modest_runtime_get_protocol_registry (),
344                                                proto_type,
345                                                MODEST_PROTOCOL_REGISTRY_MULTI_MAILBOX_PROVIDER_PROTOCOLS));
346                 }
347         }
348         
349         if (hide_account_title)
350                 gtk_widget_hide (priv->caption_account_title);
351         else
352                 gtk_widget_show (priv->caption_account_title);
353
354         hildon_entry_set_text (HILDON_ENTRY (priv->entry_account_title), default_account_name);
355         g_free (default_account_name);
356 }
357
358 /** This is a convenience function to create a caption containing a mandatory widget.
359  * When the widget is edited, the enable_buttons() vfunc will be called.
360  */
361 static GtkWidget* 
362 create_captioned (ModestEasysetupWizardDialog *self,
363                   GtkSizeGroup *title_size_group,
364                   GtkSizeGroup *value_size_group,
365                   const gchar *value,
366                   gboolean use_markup,
367                   GtkWidget *control)
368 {
369
370         GtkWidget *result;
371         result = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
372                                                       value, use_markup, control);
373
374         /* Connect to the appropriate changed signal for the widget, 
375          * so we can ask for the prev/next buttons to be enabled/disabled appropriately:
376          */
377         if (GTK_IS_ENTRY (control)) {
378                 g_signal_connect (G_OBJECT (control), "changed",
379                                   G_CALLBACK (on_caption_entry_changed), self);
380                 
381         }
382         else if (GTK_IS_COMBO_BOX (control)) {
383                 g_signal_connect (G_OBJECT (control), "changed",
384                                   G_CALLBACK (on_caption_combobox_changed), self);
385         }
386          
387         return result;
388 }
389            
390 static GtkWidget*
391 create_page_welcome (ModestEasysetupWizardDialog *self)
392 {
393         GtkWidget *box;
394         GtkWidget *align;
395         GtkWidget *label; 
396         ModestEasysetupWizardDialogPrivate *priv;
397
398         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
399         box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
400         label = gtk_label_new(_("mcen_ia_emailsetup_intro"));
401         priv->check_support_progress = gtk_progress_bar_new ();
402         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
403         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
404         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
405         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
406         /* So that it is not truncated: */
407         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
408         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
409         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
410         gtk_box_pack_end (GTK_BOX (box), priv->check_support_progress, FALSE, FALSE, 0);
411         gtk_container_add (GTK_CONTAINER (align), box);
412         gtk_widget_show (label);
413         gtk_widget_show (GTK_WIDGET (box));
414         return GTK_WIDGET (align);
415 }
416
417 static void
418 on_account_country_selector_changed (HildonTouchSelector *widget, gint column, gpointer user_data)
419 {
420         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
421         g_assert(self);
422         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
423         
424         priv->dirty = TRUE;
425         
426         /* Fill the providers picker, based on the selected country: */
427         if (priv->presets != NULL) {
428                 gint mcc = modest_country_picker_get_active_country_mcc (
429                         MODEST_COUNTRY_PICKER (priv->account_country_picker));
430                 modest_provider_picker_fill (
431                         MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker), priv->presets, mcc);
432         }
433 }
434
435 static void
436 update_user_email_from_provider (ModestEasysetupWizardDialog *self)
437 {
438         ModestEasysetupWizardDialogPrivate *priv; 
439         gchar* provider_id = NULL, *with_at = NULL;
440
441         g_assert(self);
442         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
443
444         /* Fill the providers combo, based on the selected country: */
445         provider_id = modest_provider_picker_get_active_provider_id (
446                 MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker));
447
448         if (provider_id) {
449                 gchar *domain_name = modest_presets_get_domain (priv->presets, provider_id);
450                 with_at = g_strdup_printf ("%c%s", '@', domain_name);
451                 g_free (domain_name);
452         }
453
454         /* The sample address already contains the '@' */
455         if (!with_at)
456                 with_at = g_strdup (MODEST_EXAMPLE_EMAIL_ADDRESS);
457
458         if (priv->entry_user_email)
459                 hildon_entry_set_text (HILDON_ENTRY (priv->entry_user_email), with_at);
460
461         g_free (with_at);
462         g_free (provider_id);
463 }
464
465 static void
466 on_account_serviceprovider_selector_changed (HildonTouchSelector *widget, gint column, gpointer user_data)
467 {
468         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
469         g_assert(self);
470         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
471         
472         priv->dirty = TRUE;
473
474         update_user_email_from_provider (self);
475 }
476
477 static void
478 on_entry_max (ModestValidatingEntry *self, gpointer user_data)
479 {
480         modest_platform_information_banner (GTK_WIDGET (self), NULL,
481                                             _CS("ckdg_ib_maximum_characters_reached"));
482 }
483
484 static GtkWidget*
485 create_page_account_details (ModestEasysetupWizardDialog *self)
486 {
487         GtkWidget *align;
488         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
489         GtkWidget *label = gtk_label_new(_("mcen_ia_accountdetails"));
490         ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
491
492         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
493         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
494         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
495         gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
496         gtk_widget_show (label);
497
498         /* Create a size group to be used by all captions.
499          * Note that HildonCaption does not create a default size group if we do not specify one.
500          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
501         GtkSizeGroup* title_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
502         GtkSizeGroup* value_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
503
504         /* The country widgets: */
505         priv->account_country_picker = GTK_WIDGET (modest_country_picker_new (MODEST_EDITABLE_SIZE,
506                                                                               HILDON_BUTTON_ARRANGEMENT_HORIZONTAL));
507         modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup, 
508                                                _("mcen_fi_country"), priv->account_country_picker);
509         g_signal_connect (G_OBJECT (priv->account_country_picker), "value-changed",
510                           G_CALLBACK (on_picker_button_value_changed), self);
511         gtk_box_pack_start (GTK_BOX (box), priv->account_country_picker, FALSE, FALSE, MODEST_MARGIN_HALF);
512         gtk_widget_show (priv->account_country_picker);
513         
514         /* The service provider widgets: */     
515         priv->account_serviceprovider_picker = GTK_WIDGET (modest_provider_picker_new (MODEST_EDITABLE_SIZE,
516                                                                                        HILDON_BUTTON_ARRANGEMENT_HORIZONTAL));
517         modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
518                                                _("mcen_fi_serviceprovider"), 
519                                                priv->account_serviceprovider_picker);
520         g_signal_connect (G_OBJECT (priv->account_serviceprovider_picker), "value-changed",
521                           G_CALLBACK (on_serviceprovider_picker_button_value_changed), self);
522         gtk_box_pack_start (GTK_BOX (box), priv->account_serviceprovider_picker, FALSE, FALSE, 0);
523         gtk_widget_show (priv->account_serviceprovider_picker);
524         
525         /* The description widgets: */  
526         priv->entry_account_title = GTK_WIDGET (modest_validating_entry_new ());
527         g_signal_connect(G_OBJECT(priv->entry_account_title), "changed",
528                          G_CALLBACK(on_easysetup_changed), self);
529         /* Do use auto-capitalization: */
530         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_account_title), 
531                                          HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
532         
533         /* Set a default account title, choosing one that does not already exist: */
534         /* Note that this is irrelevant to the non-user visible name, which we will create later. */
535         gchar* default_account_name_start = g_strdup (_("mcen_ia_emailsetup_defaultname"));
536         gchar* default_account_name = modest_account_mgr_get_unused_account_display_name (
537                 priv->account_manager, default_account_name_start);
538         g_free (default_account_name_start);
539         default_account_name_start = NULL;
540         
541         hildon_entry_set_text (HILDON_ENTRY (priv->entry_account_title), default_account_name);
542         g_free (default_account_name);
543         default_account_name = NULL;
544
545         priv->caption_account_title = create_captioned (self, title_sizegroup, value_sizegroup, 
546                                                         _("mcen_fi_account_title"), FALSE,
547                                                         priv->entry_account_title);
548         gtk_widget_show (priv->entry_account_title);
549         gtk_box_pack_start (GTK_BOX (box), priv->caption_account_title, FALSE, FALSE, 0);
550         gtk_widget_show (priv->caption_account_title);
551         gtk_widget_set_no_show_all (priv->caption_account_title, TRUE);
552         
553         /* Prevent the use of some characters in the account title, 
554          * as required by our UI specification: */
555         GList *list_prevent = NULL;
556         list_prevent = g_list_append (list_prevent, "\\");
557         list_prevent = g_list_append (list_prevent, "/");
558         list_prevent = g_list_append (list_prevent, ":");
559         list_prevent = g_list_append (list_prevent, "*");
560         list_prevent = g_list_append (list_prevent, "?");
561         list_prevent = g_list_append (list_prevent, "\""); /* The UI spec mentions â€œ, but maybe means ", maybe both. */
562         list_prevent = g_list_append (list_prevent, "“");
563         list_prevent = g_list_append (list_prevent, "<"); 
564         list_prevent = g_list_append (list_prevent, ">"); 
565         list_prevent = g_list_append (list_prevent, "|");
566         list_prevent = g_list_append (list_prevent, "^");       
567         modest_validating_entry_set_unallowed_characters (
568                 MODEST_VALIDATING_ENTRY (priv->entry_account_title), list_prevent);
569         g_list_free (list_prevent);
570         list_prevent = NULL;
571         modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_account_title),
572                                                                                                                                          modest_utils_on_entry_invalid_character, self);
573         
574         /* Set max length as in the UI spec:
575          * The UI spec seems to want us to show a dialog if we hit the maximum. */
576         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_account_title), 64);
577         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_account_title), 
578                                               on_entry_max, self);
579         
580         gtk_widget_show (GTK_WIDGET (box));
581
582         g_object_unref (title_sizegroup);
583         g_object_unref (value_sizegroup);
584
585         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
586         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
587         gtk_widget_show (align);
588         gtk_container_add (GTK_CONTAINER (align), box);
589         
590         return GTK_WIDGET (align);
591 }
592
593 static GtkWidget*
594 create_page_user_details (ModestEasysetupWizardDialog *self)
595 {
596         GtkSizeGroup* title_sizegroup;
597         GtkSizeGroup* value_sizegroup;
598         GtkWidget *box;
599         ModestEasysetupWizardDialogPrivate *priv;
600         GtkWidget *align;
601
602         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
603         
604         /* Create a size group to be used by all captions.
605          * Note that HildonCaption does not create a default size group if we do not specify one.
606          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
607         box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
608         title_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
609         value_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
610          
611         /* The name widgets: (use auto cap) */
612         priv->entry_user_name = GTK_WIDGET (modest_validating_entry_new ());
613         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_name), 
614                                          HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
615         
616         /* Set max length as in the UI spec:
617          * The UI spec seems to want us to show a dialog if we hit the maximum. */
618         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_name), 64);
619         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_name), 
620                                               on_entry_max, self);
621         GtkWidget *caption = create_captioned (self, title_sizegroup, value_sizegroup,
622                                                _("mcen_li_emailsetup_name"), FALSE, priv->entry_user_name);
623         g_signal_connect(G_OBJECT(priv->entry_user_name), "changed", 
624                          G_CALLBACK(on_easysetup_changed), self);
625         gtk_widget_show (priv->entry_user_name);
626         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 0);
627         gtk_widget_show (caption);
628         
629         /* Prevent the use of some characters in the name, 
630          * as required by our UI specification: */
631         GList *list_prevent = NULL;
632         list_prevent = g_list_append (list_prevent, "<");
633         list_prevent = g_list_append (list_prevent, ">");
634         modest_validating_entry_set_unallowed_characters (
635                 MODEST_VALIDATING_ENTRY (priv->entry_user_name), list_prevent);
636         modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_name),
637                 modest_utils_on_entry_invalid_character, self);
638         g_list_free (list_prevent);
639         
640         /* The username widgets: */     
641         priv->entry_user_username = GTK_WIDGET (modest_validating_entry_new ());
642         /* Auto-capitalization is the default, so let's turn it off: */
643         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_username), 
644                                          HILDON_GTK_INPUT_MODE_FULL);
645         caption = create_captioned (self, title_sizegroup, value_sizegroup, _("mail_fi_username"), FALSE,
646                                     priv->entry_user_username);
647         gtk_widget_show (priv->entry_user_username);
648         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 0);
649         g_signal_connect(G_OBJECT(priv->entry_user_username), "changed", 
650                          G_CALLBACK(on_easysetup_changed), self);
651         gtk_widget_show (caption);
652         
653         /* Prevent the use of some characters in the username, 
654          * as required by our UI specification: */
655         modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_username),
656                 modest_utils_on_entry_invalid_character, self);
657         
658         /* Set max length as in the UI spec:
659          * The UI spec seems to want us to show a dialog if we hit the maximum. */
660         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_username), 64);
661         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_username), 
662                                               on_entry_max, self);
663         
664         /* The password widgets: */     
665         priv->entry_user_password = hildon_entry_new (MODEST_EDITABLE_SIZE);
666         /* Auto-capitalization is the default, so let's turn it off: */
667         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_password), 
668                                          HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
669         gtk_entry_set_visibility (GTK_ENTRY (priv->entry_user_password), FALSE);
670         /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_user_password), '*'); */
671         caption = create_captioned (self, title_sizegroup, value_sizegroup,
672                                     _("mail_fi_password"), FALSE, priv->entry_user_password);
673         g_signal_connect(G_OBJECT(priv->entry_user_password), "changed", 
674                          G_CALLBACK(on_easysetup_changed), self);
675         gtk_widget_show (priv->entry_user_password);
676         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 0);
677         gtk_widget_show (caption);
678         
679         /* The email address widgets: */        
680         priv->entry_user_email = GTK_WIDGET (modest_validating_entry_new ());
681         /* Auto-capitalization is the default, so let's turn it off: */
682         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_user_email), HILDON_GTK_INPUT_MODE_FULL);
683         caption = create_captioned (self, title_sizegroup, value_sizegroup,
684                                     _("mcen_li_emailsetup_email_address"), FALSE, priv->entry_user_email);
685         update_user_email_from_provider (self);
686         gtk_widget_show (priv->entry_user_email);
687         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 0);
688         g_signal_connect(G_OBJECT(priv->entry_user_email), "changed", 
689                          G_CALLBACK(on_easysetup_changed), self);
690         gtk_widget_show (caption);
691         
692         /* Set max length as in the UI spec:
693          * The UI spec seems to want us to show a dialog if we hit the maximum. */
694         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_email), 64);
695         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_email), 
696                                               on_entry_max, self);
697         
698         
699         gtk_widget_show (GTK_WIDGET (box));
700         g_object_unref (title_sizegroup);
701         g_object_unref (value_sizegroup);
702
703         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
704         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
705         gtk_widget_show (align);
706         gtk_container_add (GTK_CONTAINER (align), box);
707         
708         return GTK_WIDGET (align);
709 }
710
711 static GtkWidget*
712 create_page_complete_easysetup (ModestEasysetupWizardDialog *self)
713 {
714         GtkWidget *align;
715         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
716
717         GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete"));
718         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
719         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
720         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
721         gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
722
723         gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
724         gtk_widget_show (label);
725
726         label = gtk_label_new (_("mcen_ia_easysetup_complete"));
727         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
728         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
729
730         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
731         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
732         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
733         gtk_widget_show (label);
734
735         gtk_widget_show (GTK_WIDGET (box));
736
737         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
738         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
739         gtk_widget_show (align);
740         gtk_container_add (GTK_CONTAINER (align), box);
741         
742         return GTK_WIDGET (align);
743 }
744
745 /** Change the caption title for the incoming server, 
746  * as specified in the UI spec:
747  */
748 static void 
749 update_incoming_server_title (ModestEasysetupWizardDialog *self)
750 {
751         ModestEasysetupWizardDialogPrivate* priv; 
752         ModestProtocolType protocol_type; 
753         ModestProtocolRegistry *protocol_registry;
754
755         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
756         protocol_registry = modest_runtime_get_protocol_registry ();
757
758         protocol_type = modest_servertype_picker_get_active_servertype (
759                 MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker));
760
761         /* This could happen when the combo box has still no active iter */
762         if (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
763                 gchar* incomingserver_title;
764                 const gchar *protocol_display_name;
765                 ModestProtocol *protocol;
766
767                 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, 
768                                                                           protocol_type);
769                 protocol_display_name = modest_protocol_get_display_name (protocol);
770
771                 incomingserver_title = g_strconcat (_("mcen_li_emailsetup_servertype"), "\n<small>(",
772                                                     protocol_display_name, ")</small>", NULL);
773
774                 modest_maemo_utils_captioned_set_label (priv->caption_incoming, incomingserver_title, TRUE);
775
776                 g_free(incomingserver_title);
777         }
778 }
779
780 /** Change the caption title for the incoming server, 
781  * as specified in the UI spec:
782  */
783 static void 
784 update_incoming_server_security_choices (ModestEasysetupWizardDialog *self)
785 {
786         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
787         ModestServertypePicker *server_type_picker;
788         ModestProtocolType protocol_type;
789         ModestSecurityOptionsView *view;
790
791         server_type_picker = 
792                 MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker);
793         protocol_type = 
794                 modest_servertype_picker_get_active_servertype (server_type_picker);
795         
796         /* Fill the combo with appropriately titled choices for all
797            those protocols */
798         view = MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security);
799         modest_security_options_view_set_server_type (view, protocol_type);
800 }
801
802 static void 
803 on_servertype_selector_changed(HildonTouchSelector *selector, gint column, gpointer user_data)
804 {
805         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
806         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
807         ModestServertypePicker *picker;
808         ModestProtocolType protocol_type;
809
810         priv->dirty = TRUE;
811         
812         /* Update title */
813         update_incoming_server_title (self);
814
815         /* Update security options if needed */
816         picker = MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker);
817         protocol_type = modest_servertype_picker_get_active_servertype (picker);
818         update_incoming_server_security_choices (self);
819         gtk_widget_show (priv->incoming_security);
820
821         set_default_custom_servernames (self);
822 }
823
824 static void 
825 on_entry_incoming_servername_changed(GtkEntry *entry, gpointer user_data)
826 {
827         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
828         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
829         priv->dirty = TRUE;
830         priv->server_changes |= MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED;
831 }
832
833 static GtkWidget* 
834 create_page_custom_incoming (ModestEasysetupWizardDialog *self)
835 {
836         ModestProtocolRegistry *protocol_registry;
837         ModestEasysetupWizardDialogPrivate* priv; 
838         GtkWidget *box;
839         GtkWidget *align;
840         GtkWidget *pannable;
841         GtkWidget *label;
842         GtkSizeGroup *title_sizegroup;
843         GtkSizeGroup *value_sizegroup;
844
845         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
846         protocol_registry = modest_runtime_get_protocol_registry ();
847
848         box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
849         pannable = hildon_pannable_area_new ();
850
851         /* Show note that account type cannot be changed in future: */
852         label = gtk_label_new (_("mcen_ia_emailsetup_account_type"));
853         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
854         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
855         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
856         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
857         gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
858         gtk_widget_show (label);
859         
860         /* Create a size group to be used by all captions.
861          * Note that HildonCaption does not create a default size group if we do not specify one.
862          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
863         title_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
864         value_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
865          
866         /* The incoming server widgets: */
867         priv->incoming_servertype_picker = GTK_WIDGET (modest_servertype_picker_new (MODEST_EDITABLE_SIZE,
868                                                                                      HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
869                                                                                      TRUE));
870         modest_maemo_utils_set_hbutton_layout (title_sizegroup, value_sizegroup,
871                                                _("mcen_li_emailsetup_type"),
872                                                priv->incoming_servertype_picker);
873         g_signal_connect (G_OBJECT (priv->incoming_servertype_picker), "value-changed",
874                           G_CALLBACK (on_picker_button_value_changed), self);
875         gtk_box_pack_start (GTK_BOX (box), priv->incoming_servertype_picker, FALSE, FALSE, 0);
876         gtk_widget_show (priv->incoming_servertype_picker);
877         
878         priv->entry_incomingserver = hildon_entry_new (MODEST_EDITABLE_SIZE);
879         g_signal_connect(G_OBJECT(priv->entry_incomingserver), "changed", G_CALLBACK(on_easysetup_changed), self);
880         /* Auto-capitalization is the default, so let's turn it off: */
881         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_incomingserver), HILDON_GTK_INPUT_MODE_FULL);
882         set_default_custom_servernames (self);
883
884         /* The caption title will be updated in update_incoming_server_title().
885          * so this default text will never be seen: */
886         priv->caption_incoming = create_captioned (self, title_sizegroup, value_sizegroup,
887                                                    "This will be removed", 
888                                                    FALSE, priv->entry_incomingserver);
889         update_incoming_server_title (self);
890         gtk_widget_show (priv->entry_incomingserver);
891         gtk_box_pack_start (GTK_BOX (box), priv->caption_incoming, FALSE, FALSE, 0);
892         gtk_widget_show (priv->caption_incoming);
893         
894         /* Change the caption title when the servertype changes, 
895          * as in the UI spec: */
896         g_signal_connect (G_OBJECT (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->incoming_servertype_picker))), 
897                           "changed",
898                           G_CALLBACK (on_servertype_selector_changed), self);
899
900         /* Remember when the servername was changed manually: */
901         g_signal_connect (G_OBJECT (priv->entry_incomingserver), "changed",
902                           G_CALLBACK (on_entry_incoming_servername_changed), self);
903
904         /* The secure connection widgets. These are only valid for
905            protocols with security */   
906         priv->incoming_security = 
907                 modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_INCOMING,
908                                                         FALSE, title_sizegroup, value_sizegroup);
909         gtk_box_pack_start (GTK_BOX (box), priv->incoming_security, 
910                             FALSE, FALSE, 0);
911         gtk_widget_show (priv->incoming_security);
912
913         /* Set default selection */
914         modest_servertype_picker_set_active_servertype (
915                 MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker), 
916                 MODEST_PROTOCOLS_STORE_POP);
917
918         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
919         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
920         gtk_widget_show (align);
921         gtk_container_add (GTK_CONTAINER (align), box);
922         
923         hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (pannable), align);
924         gtk_container_set_focus_vadjustment (GTK_CONTAINER (box),
925                                              hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (pannable)));
926         gtk_widget_show (GTK_WIDGET (box));
927         gtk_widget_show (pannable);
928
929         g_object_unref (title_sizegroup);
930         g_object_unref (value_sizegroup);
931
932         return GTK_WIDGET (pannable);
933 }
934
935 static void
936 on_check_button_changed (HildonCheckButton *button, gpointer user_data)
937 {
938         GtkWidget *widget = GTK_WIDGET (user_data);
939         
940         /* Enable the widget only if the check button is active: */
941         const gboolean enable = hildon_check_button_get_active (button);
942         gtk_widget_set_sensitive (widget, enable);
943 }
944
945 /* Make the sensitivity of a widget depend on a check button.
946  */
947 static void
948 enable_widget_for_checkbutton (GtkWidget *widget, HildonCheckButton* button)
949 {
950         g_signal_connect (G_OBJECT (button), "toggled",
951                           G_CALLBACK (on_check_button_changed), widget);
952         
953         /* Set the starting sensitivity: */
954         on_check_button_changed (button, widget);
955 }
956
957 static void
958 on_button_outgoing_smtp_servers (GtkButton *button, gpointer user_data)
959 {
960         ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
961         ModestEasysetupWizardDialogPrivate* priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
962         GtkWidget *specific_window;
963         
964         /* We set dirty here because setting it depending on the connection specific dialog
965         seems overkill */
966         priv->dirty = TRUE;
967         
968         /* Create the window, if necessary: */
969         specific_window = (GtkWidget *) modest_connection_specific_smtp_window_new ();
970         modest_connection_specific_smtp_window_fill_with_connections (MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), priv->account_manager);
971
972         /* Show the window */
973         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (specific_window), GTK_WINDOW (self));
974         gtk_widget_show (specific_window);
975 }
976
977 static void 
978 on_entry_outgoing_servername_changed (GtkEntry *entry, gpointer user_data)
979 {
980         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
981         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
982         priv->server_changes |= MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED;
983 }
984
985 static GtkWidget* 
986 create_page_custom_outgoing (ModestEasysetupWizardDialog *self)
987 {
988         ModestEasysetupWizardDialogPrivate *priv;
989         gchar *smtp_caption_label;
990         GtkWidget *pannable;
991         GtkWidget *align;
992         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
993
994         pannable = hildon_pannable_area_new ();
995         
996         /* Create a size group to be used by all captions.
997          * Note that HildonCaption does not create a default size group if we do not specify one.
998          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
999         GtkSizeGroup *title_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1000         GtkSizeGroup *value_sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1001          
1002         /* The outgoing server widgets: */
1003         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1004         priv->entry_outgoingserver = hildon_entry_new (MODEST_EDITABLE_SIZE);
1005         g_signal_connect (G_OBJECT (priv->entry_outgoingserver), "changed",
1006                   G_CALLBACK (on_easysetup_changed), self);
1007         /* Auto-capitalization is the default, so let's turn it off: */
1008         hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry_outgoingserver), HILDON_GTK_INPUT_MODE_FULL);
1009         smtp_caption_label = g_strconcat (_("mcen_li_emailsetup_smtp"), "\n<small>(SMTP)</small>", NULL);
1010         GtkWidget *caption = create_captioned (self, title_sizegroup, value_sizegroup,
1011                                                smtp_caption_label, TRUE, priv->entry_outgoingserver);
1012         g_free (smtp_caption_label);
1013         gtk_widget_show (priv->entry_outgoingserver);
1014         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, 0);
1015         gtk_widget_show (caption);
1016         set_default_custom_servernames (self);
1017
1018         /* The secure connection widgets. These are only valid for
1019            protocols with security */   
1020         priv->outgoing_security = 
1021                 modest_maemo_security_options_view_new (MODEST_SECURITY_OPTIONS_OUTGOING,
1022                                                         FALSE, title_sizegroup, value_sizegroup);
1023         gtk_box_pack_start (GTK_BOX (box), priv->outgoing_security, 
1024                             FALSE, FALSE, 0);
1025         gtk_widget_show (priv->outgoing_security);
1026
1027         GtkWidget *separator = gtk_hseparator_new ();
1028         gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 0);
1029         gtk_widget_show (separator);
1030
1031         /* connection-specific checkbox: */
1032         priv->checkbox_outgoing_smtp_specific = hildon_check_button_new (HILDON_SIZE_FINGER_HEIGHT);
1033         hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->checkbox_outgoing_smtp_specific), 
1034                                         FALSE);
1035         gtk_button_set_label (GTK_BUTTON (priv->checkbox_outgoing_smtp_specific),
1036                               _("mcen_fi_advsetup_connection_smtp"));
1037         gtk_button_set_alignment (GTK_BUTTON (priv->checkbox_outgoing_smtp_specific),
1038                                   0.0, 0.5);
1039         g_signal_connect (G_OBJECT (priv->checkbox_outgoing_smtp_specific), "toggled",
1040                   G_CALLBACK (on_easysetup_changed), self);
1041
1042         gtk_widget_show (priv->checkbox_outgoing_smtp_specific);
1043         gtk_box_pack_start (GTK_BOX (box), priv->checkbox_outgoing_smtp_specific,
1044                             FALSE, FALSE, 0);
1045
1046         /* Connection-specific SMTP-Severs Edit button: */
1047         priv->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_advsetup_optional_smtp"));
1048         hildon_gtk_widget_set_theme_size (priv->button_outgoing_smtp_servers, 
1049                                           HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);  
1050         gtk_widget_show (priv->button_outgoing_smtp_servers);
1051         gtk_box_pack_start (GTK_BOX (box), priv->button_outgoing_smtp_servers, 
1052                             FALSE, FALSE, 0);
1053
1054         /* Only enable the button when the checkbox is checked: */
1055         enable_widget_for_checkbutton (priv->button_outgoing_smtp_servers, 
1056                                        HILDON_CHECK_BUTTON (priv->checkbox_outgoing_smtp_specific));
1057
1058         g_signal_connect (G_OBJECT (priv->button_outgoing_smtp_servers), "clicked",
1059                           G_CALLBACK (on_button_outgoing_smtp_servers), self);
1060
1061         g_signal_connect (G_OBJECT (priv->entry_outgoingserver), "changed",
1062                           G_CALLBACK (on_entry_outgoing_servername_changed), self);
1063
1064
1065         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1066         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1067         gtk_widget_show (align);
1068         gtk_container_add (GTK_CONTAINER (align), box);
1069         
1070         hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (pannable), align);
1071         gtk_container_set_focus_vadjustment (GTK_CONTAINER (box),
1072                                              hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (pannable)));
1073         gtk_widget_show (GTK_WIDGET (box));
1074         gtk_widget_show (pannable);
1075
1076         g_object_unref (title_sizegroup);
1077         g_object_unref (value_sizegroup);
1078         
1079         return GTK_WIDGET (pannable);
1080 }
1081
1082 static gboolean
1083 show_advanced_edit(gpointer user_data)
1084 {
1085         ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
1086         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1087         gint response;
1088         
1089         /* Show the Account Settings window: */
1090         ModestAccountSettingsDialog *dialog = modest_default_account_settings_dialog_new ();
1091         if (priv->pending_load_settings) {
1092                 save_to_settings (self);
1093                 priv->pending_load_settings = FALSE;
1094         }
1095         modest_account_settings_dialog_load_settings (dialog, priv->settings);
1096         
1097         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), GTK_WINDOW (self));
1098         
1099         response = gtk_dialog_run (GTK_DIALOG (dialog));
1100
1101         gtk_widget_destroy (GTK_WIDGET (dialog));
1102         
1103         return FALSE; /* Do not call this timeout callback again. */
1104 }
1105
1106 static void
1107 on_button_edit_advanced_settings (GtkButton *button, gpointer user_data)
1108 {
1109         ModestEasysetupWizardDialog * self = MODEST_EASYSETUP_WIZARD_DIALOG (user_data);
1110         
1111         /* Show the Account Settings window: */
1112         show_advanced_edit(self);
1113 }
1114 static GtkWidget* 
1115 create_page_complete_custom (ModestEasysetupWizardDialog *self)
1116 {
1117         GtkWidget *align;
1118         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1119         GtkWidget *label = gtk_label_new(_("mcen_ia_emailsetup_setup_complete"));
1120         GtkWidget *button_edit = gtk_button_new_with_label (_("mcen_fi_advanced_settings"));
1121         hildon_gtk_widget_set_theme_size (button_edit, HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
1122         gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1123         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
1124         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1125         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
1126         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
1127         gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
1128         gtk_widget_show (label);
1129
1130         label = gtk_label_new (_("mcen_ia_customsetup_complete"));
1131         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
1132         gtk_widget_set_size_request (label, LABELS_WIDTH, -1);
1133         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1134         gtk_misc_set_padding (GTK_MISC (label), MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE);
1135         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1136         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
1137         gtk_widget_show (label);
1138
1139         gtk_widget_show (button_edit);
1140         gtk_box_pack_start (GTK_BOX (box), button_edit, FALSE, FALSE, 0);
1141
1142         g_signal_connect (G_OBJECT (button_edit), "clicked", 
1143                           G_CALLBACK (on_button_edit_advanced_settings), self);
1144
1145         gtk_widget_show (GTK_WIDGET (box));
1146
1147         align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1148         gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
1149         gtk_widget_show (align);
1150         gtk_container_add (GTK_CONTAINER (align), box);
1151         
1152         return GTK_WIDGET (align);
1153 }
1154
1155
1156 /*
1157  */
1158 static void 
1159 on_response (ModestWizardDialog *wizard_dialog,
1160              gint response_id,
1161              gpointer user_data)
1162 {
1163         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (wizard_dialog);
1164
1165         invoke_enable_buttons_vfunc (self);
1166 }
1167
1168 static void 
1169 on_response_before (ModestWizardDialog *wizard_dialog,
1170                     gint response_id,
1171                     gpointer user_data)
1172 {
1173         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (wizard_dialog);
1174         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(wizard_dialog);
1175         if (response_id == GTK_RESPONSE_CANCEL) {
1176                 /* This is mostly copied from
1177                  * src/maemo/modest-account-settings-dialog.c */
1178                 if (priv->dirty) {
1179                         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_confirmation (GTK_WINDOW (self), 
1180                                 _("imum_nc_wizard_confirm_lose_changes")));
1181                         /* TODO: These button names will be ambiguous, and not
1182                          * specified in the UI specification. */
1183
1184                         const gint dialog_response = gtk_dialog_run (dialog);
1185                         gtk_widget_destroy (GTK_WIDGET (dialog));
1186
1187                         if (dialog_response != GTK_RESPONSE_OK) {
1188                                 /* Don't let the dialog close */
1189                                 g_signal_stop_emission_by_name (wizard_dialog, "response");
1190                         }
1191                 }
1192         }
1193 }
1194
1195 static void
1196 fill_providers (ModestEasysetupWizardDialog *self)
1197 {
1198         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1199
1200         if (MODEST_IS_COUNTRY_PICKER (priv->account_country_picker)) {
1201 /*              gint mcc = get_default_country_code(); */
1202                 gint mcc;
1203                 /* Fill the combo in an idle call, as it takes a lot of time */
1204                 modest_country_picker_load_data(
1205                         MODEST_COUNTRY_PICKER (priv->account_country_picker));
1206                 /* connect to country picker's changed signal, so we can fill the provider picker: */
1207                 g_signal_connect (G_OBJECT (hildon_picker_button_get_selector 
1208                                             (HILDON_PICKER_BUTTON (priv->account_country_picker))),
1209                                   "changed",
1210                                   G_CALLBACK (on_account_country_selector_changed), self);
1211             
1212                 modest_country_picker_set_active_country_locale (
1213                         MODEST_COUNTRY_PICKER (priv->account_country_picker));
1214                 mcc = modest_country_picker_get_active_country_mcc (
1215                         MODEST_COUNTRY_PICKER (priv->account_country_picker));
1216                 modest_provider_picker_fill (
1217                         MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker),
1218                         priv->presets, mcc);
1219                 /* connect to providers picker's changed signal, so we can fill the email address: */
1220                 g_signal_connect (G_OBJECT (hildon_picker_button_get_selector 
1221                                             (HILDON_PICKER_BUTTON (priv->account_serviceprovider_picker))),
1222                                   "changed",
1223                                   G_CALLBACK (on_account_serviceprovider_selector_changed), self);
1224                 
1225                 modest_provider_picker_set_others_provider (MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker));
1226         }
1227
1228         priv->dirty = FALSE;
1229
1230 }
1231
1232 typedef struct IdleData {
1233         ModestEasysetupWizardDialog *dialog;
1234         ModestPresets *presets;
1235 } IdleData;
1236
1237 static gboolean
1238 presets_idle (gpointer userdata)
1239 {
1240         IdleData *idle_data = (IdleData *) userdata;
1241         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (idle_data->dialog);
1242         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1243
1244         g_assert (idle_data->presets);
1245
1246         gdk_threads_enter ();
1247
1248         priv->presets = idle_data->presets;
1249
1250         if (priv->check_support_done)
1251                 fill_providers (self);
1252
1253         g_object_unref (idle_data->dialog);
1254         g_free (idle_data);
1255
1256         gdk_threads_leave ();
1257
1258         return FALSE;
1259 }
1260
1261 static gpointer
1262 presets_loader (gpointer userdata)
1263 {
1264         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (userdata);
1265         ModestPresets *presets = NULL;
1266         IdleData *idle_data;
1267
1268         const gchar* path  = NULL;
1269         const gchar* path1 = MODEST_PROVIDER_DATA_FILE;
1270         const gchar* path2 = MODEST_MAEMO_PROVIDER_DATA_FILE;
1271         
1272         if (access(path1, R_OK) == 0) 
1273                 path = path1;
1274         else if (access(path2, R_OK) == 0)
1275                 path = path2;
1276         else {
1277                 g_warning ("%s: neither '%s' nor '%s' is a readable provider data file",
1278                            __FUNCTION__, path1, path2);
1279                 return NULL;
1280         }
1281
1282         presets = modest_presets_new (path);
1283         if (!presets) {
1284                 g_warning ("%s: failed to parse '%s'", __FUNCTION__, path);
1285                 return NULL;
1286         }
1287         
1288         idle_data = g_new0 (IdleData, 1);
1289         idle_data->dialog = self;
1290         idle_data->presets = presets;
1291         
1292         g_idle_add (presets_idle, idle_data);   
1293
1294         return NULL;
1295 }
1296
1297 static void
1298 modest_easysetup_wizard_dialog_append_page (GtkNotebook *notebook,
1299                                             GtkWidget *page,
1300                                             const gchar *label)
1301 {
1302         gint index;
1303         /* Append page and set attributes */
1304         index = gtk_notebook_append_page (notebook, page, gtk_label_new (label));
1305         gtk_container_child_set (GTK_CONTAINER (notebook), page,
1306                                  "tab-expand", TRUE, "tab-fill", TRUE,
1307                                  NULL);
1308         gtk_widget_show (page);
1309 }
1310
1311 static void
1312 init_user_page (ModestEasysetupWizardDialogPrivate *priv)
1313 {
1314         priv->page_user_details = NULL;
1315         priv->entry_user_name = NULL;
1316         priv->entry_user_username = NULL;
1317         priv->entry_user_password = NULL;
1318         priv->entry_user_email = NULL;
1319 }
1320
1321 static void
1322 init_incoming_page (ModestEasysetupWizardDialogPrivate *priv)
1323 {
1324         priv->page_custom_incoming = NULL;
1325         priv->incoming_servertype_picker = NULL;
1326         priv->caption_incoming = NULL;
1327         priv->entry_incomingserver = NULL;
1328         priv->entry_user_email = NULL;
1329         priv->incoming_security = NULL;
1330 }
1331
1332 static void
1333 init_outgoing_page (ModestEasysetupWizardDialogPrivate *priv)
1334 {
1335         priv->page_custom_outgoing = NULL;
1336         priv->entry_outgoingserver = NULL;
1337         priv->checkbox_outgoing_smtp_specific = NULL;
1338         priv->button_outgoing_smtp_servers = NULL;
1339         priv->outgoing_security = NULL;
1340 }
1341
1342 static void
1343 modest_easysetup_wizard_dialog_init (ModestEasysetupWizardDialog *self)
1344 {
1345         gtk_container_set_border_width (GTK_CONTAINER (self), MODEST_MARGIN_HALF);
1346         
1347         /* Create the notebook to be used by the ModestWizardDialog base class:
1348          * Each page of the notebook will be a page of the wizard: */
1349         GtkNotebook *notebook = GTK_NOTEBOOK (gtk_notebook_new());
1350         gtk_widget_set_size_request (GTK_WIDGET (notebook), -1, MODEST_DIALOG_WINDOW_MAX_HEIGHT);
1351         
1352         /* Set the notebook used by the ModestWizardDialog base class: */
1353         g_object_set (G_OBJECT(self), "wizard-notebook", notebook, NULL);
1354     
1355         /* Set the wizard title:
1356          * The actual window title will be a combination of this and the page's tab label title. */
1357         g_object_set (G_OBJECT(self), "wizard-name", _("mcen_ti_emailsetup"), NULL);
1358
1359         /* Read in the information about known service providers: */
1360         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1361         
1362         /* The server fields did not have been manually changed yet */
1363         priv->server_changes = 0;
1364         priv->pending_load_settings = TRUE;
1365
1366         /* Get the account manager object, 
1367          * so we can check for existing accounts,
1368          * and create new accounts: */
1369         priv->account_manager = modest_runtime_get_account_mgr ();
1370         g_object_ref (priv->account_manager);
1371         
1372         /* Initialize fields */
1373         priv->check_support_done = FALSE;
1374         priv->check_support_show_progress_id = 0;
1375         priv->check_support_progress_pulse_id = 0;
1376         priv->pending_check_support = 0;
1377         priv->destroyed = FALSE;
1378         priv->page_welcome = create_page_welcome (self);
1379         gtk_widget_show (priv->page_welcome);
1380         priv->page_account_details = create_page_account_details (self);
1381
1382         init_user_page (priv);
1383         init_incoming_page (priv);
1384         init_outgoing_page (priv);
1385
1386         priv->page_complete_easysetup = NULL;       
1387         priv->page_complete_customsetup = NULL;
1388         priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
1389         priv->missing_data_signals = NULL;
1390
1391         /* Add the common pages */
1392         modest_easysetup_wizard_dialog_append_page (notebook, priv->page_welcome, 
1393                                                     _("mcen_ti_emailsetup_welcome"));
1394         modest_easysetup_wizard_dialog_append_page (notebook, priv->page_account_details, 
1395                                                     _("mcen_ti_accountdetails"));
1396                 
1397         /* Connect to the dialog's response signal so we can enable/disable buttons 
1398          * for the newly-selected page, because the prev/next buttons cause response to be emitted.
1399          * Note that we use g_signal_connect_after() instead of g_signal_connect()
1400          * so that we can be enable/disable after ModestWizardDialog has done its own 
1401          * enabling/disabling of buttons.
1402          * 
1403          * HOWEVER, this doesn't work because ModestWizardDialog's response signal handler 
1404          * does g_signal_stop_emission_by_name(), stopping our signal handler from running.
1405          * 
1406          * It's not enough to connect to the notebook's switch-page signal, because 
1407          * ModestWizardDialog's "response" signal handler enables the buttons itself, 
1408          * _after_ switching the page (understandably).
1409          * (Note that if we had, if we used g_signal_connect() instead of g_signal_connect_after()
1410          * then gtk_notebook_get_current_page() would return an incorrect value.)
1411          */
1412         g_signal_connect_after (G_OBJECT (self), "response",
1413                                 G_CALLBACK (on_response), self);
1414
1415         /* This is to show a confirmation dialog when the user hits cancel */
1416         g_signal_connect (G_OBJECT (self), "response",
1417                           G_CALLBACK (on_response_before), self);
1418
1419         g_signal_connect (G_OBJECT (self), "delete-event",
1420                           G_CALLBACK (on_delete_event), self);
1421
1422         /* Reset dirty, because there was no user input until now */
1423         priv->dirty = FALSE;
1424
1425         /* When this window is shown, hibernation should not be possible, 
1426          * because there is no sensible way to save the state: */
1427         modest_window_mgr_prevent_hibernation_while_window_is_shown (
1428                 modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
1429
1430         /* Load provider presets */
1431         g_object_ref (self);
1432         g_thread_create (presets_loader, self, FALSE, NULL);
1433
1434         priv->settings = modest_account_settings_new ();
1435
1436         check_support_of_protocols (self);
1437 }
1438
1439 ModestEasysetupWizardDialog*
1440 modest_easysetup_wizard_dialog_new (void)
1441 {       
1442         
1443         return g_object_new (MODEST_TYPE_EASYSETUP_WIZARD_DIALOG, NULL);
1444 }
1445
1446 static void 
1447 create_subsequent_customsetup_pages (ModestEasysetupWizardDialog *self)
1448 {
1449         ModestEasysetupWizardDialogPrivate *priv;
1450         GtkNotebook *notebook = NULL;
1451
1452         g_object_get (self, "wizard-notebook", &notebook, NULL);
1453         g_assert(notebook);
1454
1455         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1456
1457         if (!priv->page_user_details) {
1458                 priv->page_user_details = create_page_user_details (self);
1459         }                       
1460
1461         /* Create the custom pages: */
1462         if(!(priv->page_custom_incoming)) {
1463                 priv->page_custom_incoming = create_page_custom_incoming (self);
1464         }
1465                 
1466         /* TODO: only if needed */
1467         if(!(priv->page_custom_outgoing)) {
1468                 priv->page_custom_outgoing = create_page_custom_outgoing (self);
1469         }
1470         
1471         if(!(priv->page_complete_customsetup)) {
1472                 priv->page_complete_customsetup = create_page_complete_custom (self);
1473         }
1474
1475         if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_user_details)))
1476                 modest_easysetup_wizard_dialog_append_page (notebook, priv->page_user_details,
1477                                                             _("mcen_ti_emailsetup_userdetails"));
1478
1479         if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_custom_incoming)))
1480                 modest_easysetup_wizard_dialog_append_page (notebook, priv->page_custom_incoming, 
1481                                                             _("mcen_ti_emailsetup_incomingdetails"));
1482         
1483         if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_custom_outgoing)))           
1484                 modest_easysetup_wizard_dialog_append_page (notebook, priv->page_custom_outgoing, 
1485                                                             _("mcen_ti_emailsetup_outgoingdetails"));
1486                 
1487         if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_complete_customsetup)))
1488                 modest_easysetup_wizard_dialog_append_page (notebook, priv->page_complete_customsetup, 
1489                                                             _("mcen_ti_emailsetup_complete"));
1490                         
1491         /* This is unnecessary with GTK+ 2.10: */
1492         modest_wizard_dialog_force_title_update (MODEST_WIZARD_DIALOG(self));
1493 }
1494         
1495 static void 
1496 create_subsequent_easysetup_pages (ModestEasysetupWizardDialog *self)
1497 {
1498         ModestEasysetupWizardDialogPrivate *priv;
1499         GtkNotebook *notebook = NULL;
1500
1501         g_object_get (self, "wizard-notebook", &notebook, NULL);
1502         g_assert(notebook);
1503         
1504         /* Create the easysetup-specific pages: */
1505         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1506         if(!priv->page_complete_easysetup)
1507                 priv->page_complete_easysetup = create_page_complete_easysetup (self);
1508
1509         if (!gtk_widget_get_parent (GTK_WIDGET (priv->page_complete_easysetup)))
1510                 modest_easysetup_wizard_dialog_append_page (notebook, priv->page_complete_easysetup, 
1511                                                             _("mcen_ti_emailsetup_complete"));
1512                         
1513         /* This is unnecessary with GTK+ 2.10: */
1514         modest_wizard_dialog_force_title_update (MODEST_WIZARD_DIALOG(self));
1515 }
1516
1517 /* */
1518 static void
1519 remove_non_common_tabs (GtkNotebook *notebook, 
1520                         gboolean remove_user_details) 
1521 {
1522         gint starting_tab;
1523         /* The first 2 tabs are the common ones (welcome tab and the
1524            providers tab), so we always remove starting from the
1525            end */
1526
1527         starting_tab = (remove_user_details) ? 2 : 3;
1528         while (gtk_notebook_get_n_pages (notebook) > starting_tab) 
1529                 gtk_notebook_remove_page (notebook, -1); 
1530 }
1531
1532 static void
1533 on_missing_mandatory_data (ModestAccountProtocol *protocol,
1534                            gboolean missing,
1535                            gpointer user_data)
1536 {
1537         real_enable_buttons (MODEST_WIZARD_DIALOG (user_data), !missing);
1538 }
1539
1540 /* After the user details page,
1541  * the following pages depend on whether "Other" was chosen 
1542  * in the provider combobox on the account page
1543  */
1544 static void 
1545 create_subsequent_pages (ModestEasysetupWizardDialog *self)
1546 {
1547         ModestEasysetupWizardDialogPrivate *priv;
1548         ModestProviderPicker *picker;
1549         ModestProviderPickerIdType id_type;
1550         GtkNotebook *notebook;
1551
1552         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1553         picker = MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker);
1554         id_type = modest_provider_picker_get_active_id_type (picker);
1555         g_object_get (self, "wizard-notebook", &notebook, NULL);
1556         modest_wizard_dialog_set_response_override_handler (MODEST_WIZARD_DIALOG (self),
1557                                                             NULL);
1558         
1559
1560         if (id_type == MODEST_PROVIDER_PICKER_ID_OTHER) {
1561                 /* "Other..." was selected: */
1562
1563                 /* If we come from a rollbacked easysetup */
1564                 if (priv->page_complete_easysetup) {
1565                         remove_non_common_tabs (notebook, FALSE);
1566                         priv->page_complete_easysetup = NULL;
1567                 } 
1568                 
1569                 /* If we come from a rollbacked plugin protocol setup */
1570                 if (priv->last_plugin_protocol_selected != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1571                         remove_non_common_tabs (notebook, TRUE);
1572                         priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
1573                         modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
1574                         priv->missing_data_signals = NULL;
1575                 }
1576
1577                 create_subsequent_customsetup_pages (self);
1578         } else {
1579                 /* If we come from a rollbacked custom setup */
1580                 if (priv->page_custom_incoming) {
1581                         remove_non_common_tabs (notebook, TRUE);
1582                         init_user_page (priv);
1583                         init_incoming_page (priv);
1584                         init_outgoing_page (priv);
1585                         init_user_page (priv);
1586                         priv->page_complete_customsetup = NULL;
1587                 }
1588
1589                 /* It's a pluggable protocol and not a provider with presets */
1590                 if (id_type == MODEST_PROVIDER_PICKER_ID_PLUGIN_PROTOCOL) {
1591                         ModestProtocol *protocol;
1592                         gchar *proto_name;
1593                         ModestProtocolType proto_type;
1594
1595                         
1596                         /* If we come from a rollbacked easy setup */
1597                         if (priv->last_plugin_protocol_selected == 
1598                             MODEST_PROTOCOL_REGISTRY_TYPE_INVALID &&
1599                             priv->page_complete_easysetup) {
1600                                 remove_non_common_tabs (notebook, TRUE);
1601                                 init_user_page (priv);
1602                                 priv->page_complete_easysetup = NULL;
1603                         }
1604                         
1605                         proto_name = modest_provider_picker_get_active_provider_id (picker);
1606                         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
1607                                                                                   MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS,
1608                                                                                   proto_name);
1609                         proto_type = modest_protocol_get_type_id (protocol);
1610
1611                         if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol) &&
1612                             proto_type != priv->last_plugin_protocol_selected) {
1613                                 ModestPairList *tabs;
1614                                 GSList *tmp;
1615                                 gboolean first_page = TRUE;
1616                                 ModestWizardDialogResponseOverrideFunc response_override;
1617
1618                                 /* Remember the last selected plugin protocol */
1619                                 priv->last_plugin_protocol_selected = proto_type;
1620
1621                                 /* Get tabs */
1622                                 tabs = modest_account_protocol_get_easysetupwizard_tabs (MODEST_ACCOUNT_PROTOCOL (protocol));
1623                                 response_override = modest_account_protocol_get_wizard_response_override 
1624                                         (MODEST_ACCOUNT_PROTOCOL (protocol));
1625                                 modest_wizard_dialog_set_response_override_handler (MODEST_WIZARD_DIALOG (self),
1626                                                                                     response_override);
1627                                 tmp = (GSList *) tabs;
1628                                 while (tmp) {
1629                                         ModestPair *pair = (ModestPair *) tmp->data;
1630                                         modest_easysetup_wizard_dialog_append_page (notebook,
1631                                                                                     GTK_WIDGET (pair->second),
1632                                                                                     (const gchar *) pair->first);
1633                                         if (first_page) {
1634                                                 gtk_container_set_focus_child (GTK_CONTAINER (notebook),
1635                                                                                GTK_WIDGET (pair->second));
1636                                                 first_page = FALSE;
1637                                         }
1638
1639                                         /* Connect signals */
1640                                         if (MODEST_IS_EASYSETUP_WIZARD_PAGE (pair->second)) {
1641                                                 priv->missing_data_signals = 
1642                                                         modest_signal_mgr_connect (priv->missing_data_signals, 
1643                                                                                    G_OBJECT (pair->second), 
1644                                                                                    "missing-mandatory-data",
1645                                                                                    G_CALLBACK (on_missing_mandatory_data), 
1646                                                                                    self);
1647                                         }
1648
1649                                         g_free (pair->first);
1650                                         tmp = g_slist_next (tmp);
1651                                         /* Critical: if you don't show the page then the dialog will ignore it */
1652 /*                                      gtk_widget_show (GTK_WIDGET (pair->second)); */
1653                                 }
1654                                 modest_pair_list_free (tabs);
1655                         }
1656                         g_free (proto_name);
1657                 } else {
1658                         if (priv->last_plugin_protocol_selected != 
1659                             MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1660                                 remove_non_common_tabs (notebook, TRUE);
1661                                 init_user_page (priv);
1662                                 priv->page_complete_easysetup = NULL;
1663                                 priv->last_plugin_protocol_selected = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
1664                                 modest_signal_mgr_disconnect_all_and_destroy (priv->missing_data_signals);
1665                                 priv->missing_data_signals = NULL;
1666                         }
1667                         if (!priv->page_user_details) {
1668                                 priv->page_user_details = create_page_user_details (self);
1669                                 modest_easysetup_wizard_dialog_append_page (notebook, 
1670                                                                             priv->page_user_details,
1671                                                                             _("mcen_ti_emailsetup_userdetails"));
1672                         }
1673                 }
1674                 
1675                 /* Create the easysetup pages: */
1676                 create_subsequent_easysetup_pages (self);
1677         }
1678 }
1679
1680
1681 static gchar*
1682 util_get_default_servername_from_email_address (const gchar* email_address, ModestProtocolType protocol_type)
1683 {
1684         const gchar* hostname = NULL;
1685         gchar* at;
1686         gchar* domain;
1687         ModestProtocolRegistry *protocol_registry;
1688         ModestProtocol *protocol;
1689
1690         if (!email_address)
1691                 return NULL;
1692         
1693         at = g_utf8_strchr (email_address, -1, '@');
1694         if (!at || (g_utf8_strlen (at, -1) < 2))
1695                 return NULL;
1696                 
1697         domain = g_utf8_next_char (at);
1698         if(!domain)
1699                 return NULL;
1700
1701         protocol_registry = modest_runtime_get_protocol_registry ();
1702         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
1703                 
1704         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry, protocol_type, MODEST_PROTOCOL_REGISTRY_REMOTE_STORE_PROTOCOLS) ||
1705             modest_protocol_registry_protocol_type_has_tag (protocol_registry, protocol_type, MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS)) {
1706                 hostname = modest_protocol_get_name (protocol);
1707         }
1708         
1709         if (!hostname)
1710                 return NULL;
1711                 
1712         return g_strdup_printf ("%s.%s", hostname, domain);
1713 }
1714
1715 static void 
1716 set_default_custom_servernames (ModestEasysetupWizardDialog *self)
1717 {
1718         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
1719
1720         if (!priv->entry_incomingserver)
1721                 return;
1722                 
1723         /* Set a default domain for the server, based on the email address,
1724          * if no server name was already specified.
1725          */
1726         if (priv->entry_user_email
1727             && ((priv->server_changes & MODEST_EASYSETUP_WIZARD_DIALOG_INCOMING_CHANGED) == 0)) {
1728                 const ModestProtocolType protocol_type = modest_servertype_picker_get_active_servertype (
1729                         MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker));
1730
1731                 /* This could happen when the combo box has still no active iter */
1732                 if (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1733                         const gchar* email_address = hildon_entry_get_text (HILDON_ENTRY(priv->entry_user_email));      
1734                         gchar* servername = util_get_default_servername_from_email_address (email_address, 
1735                                                                                             protocol_type);
1736
1737                         /* Do not set the INCOMING_CHANGED flag because of this edit */
1738                         g_signal_handlers_block_by_func (G_OBJECT (priv->entry_incomingserver), G_CALLBACK (on_entry_incoming_servername_changed), self);
1739                         hildon_entry_set_text (HILDON_ENTRY (priv->entry_incomingserver), servername);
1740                         g_signal_handlers_unblock_by_func (G_OBJECT (priv->entry_incomingserver), G_CALLBACK (on_entry_incoming_servername_changed), self);
1741                         
1742                         g_free (servername);
1743                 }
1744         }
1745         
1746         /* Set a default domain for the server, based on the email address,
1747          * if no server name was already specified.
1748          */
1749         if (!priv->entry_outgoingserver)
1750                 return;
1751                 
1752         if (priv->entry_user_email
1753             && ((priv->server_changes & MODEST_EASYSETUP_WIZARD_DIALOG_OUTGOING_CHANGED) == 0)) {
1754                 const gchar* email_address = hildon_entry_get_text (HILDON_ENTRY(priv->entry_user_email));
1755                 
1756                 gchar* servername = util_get_default_servername_from_email_address (email_address, MODEST_PROTOCOLS_TRANSPORT_SMTP);
1757
1758                 /* Do not set the OUTGOING_CHANGED flag because of this edit */
1759                 g_signal_handlers_block_by_func (G_OBJECT (priv->entry_outgoingserver), G_CALLBACK (on_entry_outgoing_servername_changed), self);
1760                 hildon_entry_set_text (HILDON_ENTRY (priv->entry_outgoingserver), servername);
1761                 g_signal_handlers_unblock_by_func (G_OBJECT (priv->entry_outgoingserver), G_CALLBACK (on_entry_outgoing_servername_changed), self);
1762
1763                 g_free (servername);
1764         }
1765 }
1766
1767 static gchar*
1768 get_entered_account_title (ModestEasysetupWizardDialog *self)
1769 {
1770         ModestEasysetupWizardDialogPrivate *priv;
1771         const gchar* account_title;
1772
1773         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE(self);
1774         account_title = hildon_entry_get_text (HILDON_ENTRY (priv->entry_account_title));
1775
1776         if (!account_title || (g_utf8_strlen (account_title, -1) == 0)) {
1777                 return NULL;
1778         } else {
1779                 /* Strip it of whitespace at the start and end: */
1780                 gchar *result = g_strdup (account_title);
1781                 result = g_strstrip (result);
1782                 
1783                 if (!result)
1784                         return NULL;
1785                         
1786                 if (g_utf8_strlen (result, -1) == 0) {
1787                         g_free (result);
1788                         return NULL;    
1789                 }
1790                 
1791                 return result;
1792         }
1793 }
1794
1795 static gboolean
1796 on_before_next (ModestWizardDialog *dialog, GtkWidget *current_page, GtkWidget *next_page)
1797 {
1798         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
1799         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1800         ModestProtocolRegistry *protocol_registry;
1801
1802         protocol_registry = modest_runtime_get_protocol_registry ();
1803
1804         /* if are browsing pages previous to the last one, then we have pending settings in
1805          * this wizard */
1806         if (next_page != NULL)
1807                 priv->pending_load_settings = TRUE;
1808         
1809         /* Do extra validation that couldn't be done for every key press,
1810          * either because it was too slow,
1811          * or because it requires interaction:
1812          */
1813         if (current_page == priv->page_account_details) {       
1814                 /* Check that the title is not already in use: */
1815                 gchar* account_title = get_entered_account_title (self);
1816                 if (!account_title)
1817                         return FALSE;
1818                         
1819                 /* Aavoid a clash with an existing display name: */
1820                 const gboolean name_in_use = modest_account_mgr_account_with_display_name_exists (
1821                         priv->account_manager, account_title);
1822                 g_free (account_title);
1823
1824                 if (name_in_use) {
1825                         /* Warn the user via a dialog: */
1826                         hildon_banner_show_information(NULL, NULL, _("mail_ib_account_name_already_existing"));
1827             
1828                         return FALSE;
1829                 }
1830
1831                 /* Make sure that the subsequent pages are appropriate for the provider choice. */
1832                 create_subsequent_pages (self);
1833
1834         } else if (current_page == priv->page_user_details) {
1835                 /* Check that the email address is valud: */
1836                 const gchar* email_address = hildon_entry_get_text (HILDON_ENTRY (priv->entry_user_email));
1837                 if ((!email_address) || (g_utf8_strlen (email_address, -1) == 0))
1838                         return FALSE;
1839                         
1840                 if (!modest_text_utils_validate_email_address (email_address, NULL)) {
1841                         /* Warn the user via a dialog: */
1842                         hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_email"));
1843                                              
1844                         /* Return focus to the email address entry: */
1845                         gtk_widget_grab_focus (priv->entry_user_email);
1846                         gtk_editable_select_region (GTK_EDITABLE (priv->entry_user_email), 0, -1);
1847
1848                         return FALSE;
1849                 }
1850         }
1851           
1852         if (next_page == priv->page_custom_incoming) {
1853                 set_default_custom_servernames (self);
1854         } else if (next_page == priv->page_custom_outgoing) {
1855                 set_default_custom_servernames (self);
1856
1857                 /* Check if the server supports secure authentication */
1858                 if (modest_security_options_view_auth_check (MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security)))
1859                         if (!check_has_supported_auth_methods (self))
1860                                 return FALSE;
1861                 gtk_widget_show (priv->outgoing_security);
1862         }
1863         
1864         /* If this is the last page, and this is a click on Finish, 
1865          * then attempt to create the dialog.
1866          */
1867         if(!next_page && 
1868            current_page != priv->page_account_details) /* This is NULL when this is a click on Finish. */
1869         {
1870                 if (priv->pending_load_settings) {
1871                         save_to_settings (self);
1872                 }
1873
1874                 /* We check if there's already another account with the same configuration */
1875                 if (modest_account_mgr_check_already_configured_account (priv->account_manager, priv->settings)) {
1876                         modest_platform_information_banner (NULL, NULL, _("mail_ib_setting_failed"));
1877                         return FALSE;
1878                 }
1879
1880                 modest_account_mgr_add_account_from_settings (priv->account_manager, priv->settings);
1881         }
1882         
1883         
1884         return TRUE;
1885 }
1886
1887 static gboolean entry_is_empty (GtkWidget *entry)
1888 {
1889         if (!entry)
1890                 return FALSE;
1891                 
1892         const gchar* text = hildon_entry_get_text (HILDON_ENTRY (entry));
1893         if ((!text) || (g_utf8_strlen (text, -1) == 0))
1894                 return TRUE;
1895         else {
1896                 /* Strip it of whitespace at the start and end: */
1897                 gchar *stripped = g_strdup (text);
1898                 stripped = g_strstrip (stripped);
1899                 
1900                 if (!stripped)
1901                         return TRUE;
1902                         
1903                 const gboolean result = (g_utf8_strlen (stripped, -1) == 0);
1904                 
1905                 g_free (stripped);
1906                 return result;
1907         }
1908 }
1909
1910 static void
1911 real_enable_buttons (ModestWizardDialog *dialog, gboolean enable_next)
1912 {               
1913         GtkNotebook *notebook = NULL;
1914         gboolean is_finish_tab;
1915         GtkWidget *current;
1916         ModestEasysetupWizardDialogPrivate *priv;
1917
1918         /* Get data */
1919         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (dialog);
1920         g_object_get (dialog, "wizard-notebook", &notebook, NULL);
1921
1922         /* Disable the Finish button until we are on the last page,
1923          * because HildonWizardDialog enables this for all but the
1924          * first page */
1925         current = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
1926         is_finish_tab = ((current == priv->page_complete_easysetup) ||
1927                          (current == priv->page_complete_customsetup));
1928
1929         if (is_finish_tab) {
1930                 /* Disable Next on the last page no matter what the
1931                    argument say */
1932                 enable_next = FALSE;
1933         } else {
1934                 /* Not the last one */
1935                 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
1936                                                    MODEST_WIZARD_DIALOG_FINISH,
1937                                                    FALSE);
1938
1939                 /* If the check support is not done then do not enable
1940                    the wizard to continue */
1941                 enable_next = enable_next && priv->check_support_done;
1942         }
1943
1944         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
1945                                            MODEST_WIZARD_DIALOG_NEXT,
1946                                            enable_next);
1947 }
1948
1949 static void
1950 on_enable_buttons (ModestWizardDialog *dialog, GtkWidget *current_page)
1951 {
1952         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
1953         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
1954         
1955         gboolean enable_next = TRUE;
1956         if (current_page == priv->page_welcome) {
1957                 enable_next = TRUE;
1958         } else if (current_page == priv->page_account_details) {
1959                 /* The account details title is mandatory: */
1960                 if (entry_is_empty(priv->entry_account_title))
1961                         enable_next = FALSE;
1962         } else if (current_page == priv->page_user_details) {   
1963                 /* The user details username is mandatory: */
1964                 if (entry_is_empty(priv->entry_user_username))
1965                         enable_next = FALSE;
1966                         
1967                 /* The user details email address is mandatory: */
1968                 if (enable_next && entry_is_empty (priv->entry_user_email))
1969                         enable_next = FALSE;
1970         } else if (current_page == priv->page_custom_incoming) {
1971                 /* The custom incoming server is mandatory: */
1972                 if (entry_is_empty(priv->entry_incomingserver))
1973                         enable_next = FALSE;
1974         } else if (MODEST_IS_EASYSETUP_WIZARD_PAGE (current_page)) {
1975                 enable_next = !modest_easysetup_wizard_page_validate (
1976                        MODEST_EASYSETUP_WIZARD_PAGE (current_page));
1977         }
1978                         
1979         /* Enable/disable buttons */ 
1980         real_enable_buttons (dialog, enable_next);
1981 }
1982
1983 static void
1984 modest_easysetup_wizard_dialog_class_init (ModestEasysetupWizardDialogClass *klass)
1985 {
1986         GObjectClass *object_class = G_OBJECT_CLASS (klass);
1987         g_type_class_add_private (klass, sizeof (ModestEasysetupWizardDialogPrivate));
1988
1989
1990         object_class->dispose = modest_easysetup_wizard_dialog_dispose;
1991         object_class->finalize = modest_easysetup_wizard_dialog_finalize;
1992         
1993         /* Provide a vfunc implementation so we can decide 
1994          * when to enable/disable the prev/next buttons.
1995          */
1996         ModestWizardDialogClass *base_klass = (ModestWizardDialogClass*)(klass);
1997         base_klass->before_next = on_before_next;
1998         base_klass->enable_buttons = on_enable_buttons;
1999         base_klass->update_model = on_update_model;
2000         base_klass->save = on_save;
2001 }
2002
2003 /**
2004  * save_to_settings:
2005  * @self: a #ModestEasysetupWizardDialog
2006  *
2007  * takes information from all the wizard and stores it in settings
2008  */
2009 static void
2010 save_to_settings (ModestEasysetupWizardDialog *self)
2011 {
2012         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2013         guint special_port;
2014         gchar *provider_id = NULL;
2015         gchar* display_name;
2016         const gchar *username, *password;
2017         gchar *store_hostname, *transport_hostname;
2018         guint store_port, transport_port;
2019         ModestProtocolRegistry *protocol_registry;
2020         ModestProtocolType store_protocol, transport_protocol;
2021         ModestProtocolType store_security, transport_security;
2022         ModestProtocolType store_auth_protocol, transport_auth_protocol;
2023         ModestServerAccountSettings *store_settings, *transport_settings;
2024         const gchar *fullname, *email_address;
2025         ModestProviderPicker *picker;
2026         ModestProviderPickerIdType id_type;
2027
2028         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2029         picker = MODEST_PROVIDER_PICKER (priv->account_serviceprovider_picker);
2030         protocol_registry = modest_runtime_get_protocol_registry ();
2031
2032         /* Get details from the specified presets: */
2033         id_type = modest_provider_picker_get_active_id_type (picker);
2034         provider_id = modest_provider_picker_get_active_provider_id (picker);
2035
2036         /* Let the plugin save the settings. We do a return in order
2037            to save an indentation level */
2038         if (id_type == MODEST_PROVIDER_PICKER_ID_PLUGIN_PROTOCOL) {
2039                 ModestProtocol *protocol;
2040
2041                 protocol = modest_protocol_registry_get_protocol_by_name (
2042                        modest_runtime_get_protocol_registry (),
2043                        MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS,
2044                        provider_id);
2045
2046                 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
2047                         gint n_pages, i = 0;
2048                         GtkNotebook *notebook;
2049                         GList *wizard_pages = NULL;
2050
2051                         g_object_get (self, "wizard-notebook", &notebook, NULL);
2052                         n_pages = gtk_notebook_get_n_pages (notebook);
2053                         for (i = 0; i < n_pages; i++) {
2054                                 GtkWidget *page = gtk_notebook_get_nth_page (notebook, i);
2055                                 if (MODEST_IS_EASYSETUP_WIZARD_PAGE (page))
2056                                         wizard_pages  = g_list_append (wizard_pages, page);
2057                         }
2058                         modest_account_protocol_save_wizard_settings (MODEST_ACCOUNT_PROTOCOL (protocol),
2059                                                                       wizard_pages,
2060                                                                       priv->settings);
2061                         g_list_free (wizard_pages);
2062                 } else {
2063                         g_warning ("The selected protocol is a plugin protocol "//
2064                                    "but it's not a ModestAccountProtocol");
2065                 }
2066
2067                 g_free (provider_id);
2068                 return;
2069         }
2070
2071         /* username and password (for both incoming and outgoing): */
2072         username = hildon_entry_get_text (HILDON_ENTRY (priv->entry_user_username));
2073         password = hildon_entry_get_text (HILDON_ENTRY (priv->entry_user_password));
2074
2075         store_settings = modest_account_settings_get_store_settings (priv->settings);
2076         transport_settings = modest_account_settings_get_transport_settings (priv->settings);
2077
2078         /* Incoming server: */
2079         /* Note: We need something as default for the transport store protocol values, 
2080          * or modest_account_mgr_add_server_account will fail. */
2081         store_port = 0;
2082         store_protocol = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2083         store_security = MODEST_PROTOCOLS_CONNECTION_NONE;
2084         store_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
2085
2086         if (provider_id) {
2087                 ModestProtocolType store_provider_server_type;
2088                 gboolean store_provider_use_alternate_port;
2089                 /* Use presets: */
2090                 store_hostname = modest_presets_get_server (priv->presets, provider_id,
2091                                                             TRUE /* store */);
2092
2093                 store_provider_server_type = modest_presets_get_info_server_type (priv->presets,
2094                                                                          provider_id,
2095                                                                          TRUE /* store */);
2096                 store_security  = modest_presets_get_info_server_security (priv->presets,
2097                                                                            provider_id,
2098                                                                            TRUE /* store */);
2099                 store_auth_protocol  = modest_presets_get_info_server_auth (priv->presets,
2100                                                                             provider_id,
2101                                                                             TRUE /* store */);
2102                 store_provider_use_alternate_port  = modest_presets_get_info_server_use_alternate_port (priv->presets,
2103                                                                                                         provider_id,
2104                                                                                                         TRUE /* store */);
2105
2106                 /* We don't check for SMTP here as that is impossible for an incoming server. */
2107                 if (store_provider_server_type == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID)
2108                         store_protocol = MODEST_PROTOCOLS_STORE_POP;
2109                 else
2110                         store_protocol = store_provider_server_type;
2111
2112                 /* we check if there is a *special* port */
2113                 special_port = modest_presets_get_port (priv->presets, provider_id, TRUE /* incoming */);
2114                 if (special_port != 0) {
2115                         store_port = special_port;
2116                 } else {
2117                         gboolean use_alternate_port = FALSE;
2118                         if (modest_protocol_registry_protocol_type_is_secure (modest_runtime_get_protocol_registry (),
2119                                                                               store_security))
2120                                 use_alternate_port = TRUE;
2121                         store_port = get_port_from_protocol(store_provider_server_type, use_alternate_port);
2122                 }
2123
2124                 modest_server_account_settings_set_security_protocol (store_settings, 
2125                                                                       store_security);
2126                 modest_server_account_settings_set_auth_protocol (store_settings, 
2127                                                                   store_auth_protocol);
2128                 if (store_port != 0)
2129                         modest_server_account_settings_set_port (store_settings, store_port);
2130         } else {
2131                 /* Use custom pages because no preset was specified: */
2132                 store_hostname = g_strdup (hildon_entry_get_text (HILDON_ENTRY (priv->entry_incomingserver) ));         
2133                 store_protocol = modest_servertype_picker_get_active_servertype (
2134                         MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker));           
2135
2136                 modest_security_options_view_save_settings (
2137                                     MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security),
2138                                     priv->settings);
2139         }
2140
2141         /* now we store the common store account settings */
2142         modest_server_account_settings_set_hostname (store_settings, store_hostname);
2143         modest_server_account_settings_set_username (store_settings, username);
2144         modest_server_account_settings_set_password (store_settings, password);
2145         modest_server_account_settings_set_protocol (store_settings, store_protocol);
2146
2147         g_object_unref (store_settings);
2148         g_free (store_hostname);
2149         
2150         /* Outgoing server: */
2151         transport_hostname = NULL;
2152         transport_protocol = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2153         transport_security = MODEST_PROTOCOLS_CONNECTION_NONE;
2154         transport_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
2155         transport_port = 0;
2156         
2157         if (provider_id) {
2158                 ModestProtocolType transport_provider_server_type;
2159                 ModestProtocolType transport_provider_security;
2160
2161                 /* Use presets */
2162                 transport_hostname = modest_presets_get_server (priv->presets, provider_id, 
2163                                                                 FALSE /* transport */);
2164                         
2165                 transport_provider_server_type = modest_presets_get_info_server_type (priv->presets,
2166                                                                                       provider_id, 
2167                                                                                       FALSE /* transport */);           
2168                 transport_provider_security = modest_presets_get_info_server_security (priv->presets, 
2169                                                                                        provider_id, 
2170                                                                                        FALSE /* transport */);
2171
2172                 /* Note: We need something as default, or modest_account_mgr_add_server_account will fail. */
2173                 transport_protocol = transport_provider_server_type;
2174                 transport_security = transport_provider_security;
2175                 if (transport_security == MODEST_PROTOCOLS_CONNECTION_SSL) {
2176                         /* printf("DEBUG: %s: using secure SMTP\n", __FUNCTION__); */
2177                         /* we check if there is a *special* port */
2178                         special_port = modest_presets_get_port (priv->presets, provider_id,
2179                                                                 FALSE /* transport */);
2180                         if (special_port != 0)
2181                                 transport_port = special_port;
2182                         else 
2183                                 transport_port = 465;
2184                         transport_auth_protocol = MODEST_PROTOCOLS_AUTH_PASSWORD;
2185                 } else {
2186                         /* printf("DEBUG: %s: using non-secure SMTP\n", __FUNCTION__); */
2187                         transport_auth_protocol = MODEST_PROTOCOLS_AUTH_NONE;
2188                 }
2189
2190                 modest_server_account_settings_set_security_protocol (transport_settings, 
2191                                                                       transport_security);
2192                 modest_server_account_settings_set_auth_protocol (transport_settings, 
2193                                                                   transport_auth_protocol);
2194                 if (transport_port != 0)
2195                         modest_server_account_settings_set_port (transport_settings, 
2196                                                                  transport_port);
2197         } else {
2198                 ModestProtocolRegistry *registry;
2199                 ModestProtocol *store_proto;
2200
2201                 registry = modest_runtime_get_protocol_registry ();
2202                 /* Use custom pages because no preset was specified: */
2203                 transport_hostname = g_strdup (hildon_entry_get_text (HILDON_ENTRY (priv->entry_outgoingserver) ));
2204
2205                 store_proto = modest_protocol_registry_get_protocol_by_type (registry, 
2206                                                                              store_protocol);
2207
2208                 if (transport_protocol == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2209                         /* fallback to SMTP if none was specified */
2210                         g_warning ("No transport protocol was specified for store %d (%s)",
2211                                    modest_protocol_get_type_id (store_proto),
2212                                    modest_protocol_get_display_name (store_proto));
2213                         transport_protocol = MODEST_PROTOCOLS_TRANSPORT_SMTP;
2214                 }
2215
2216                 modest_security_options_view_save_settings (
2217                                     MODEST_SECURITY_OPTIONS_VIEW (priv->outgoing_security),
2218                                     priv->settings);
2219         }
2220
2221         /* now we store the common transport account settings */
2222         modest_server_account_settings_set_hostname (transport_settings, transport_hostname);
2223         modest_server_account_settings_set_username (transport_settings, username);
2224         modest_server_account_settings_set_password (transport_settings, password);
2225         modest_server_account_settings_set_protocol (transport_settings, transport_protocol);
2226
2227         g_object_unref (transport_settings);
2228         g_free (transport_hostname);
2229
2230         fullname = hildon_entry_get_text (HILDON_ENTRY (priv->entry_user_name));
2231         email_address = hildon_entry_get_text (HILDON_ENTRY (priv->entry_user_email));
2232         modest_account_settings_set_fullname (priv->settings, fullname);
2233         modest_account_settings_set_email_address (priv->settings, email_address);
2234         /* we don't set retrieve type to preserve advanced settings if
2235            any. By default account settings are set to headers only */
2236
2237         /* Save the connection-specific SMTP server accounts. */
2238         if (priv->checkbox_outgoing_smtp_specific) {
2239                 modest_account_settings_set_use_connection_specific_smtp
2240                         (priv->settings,
2241                          hildon_check_button_get_active(HILDON_CHECK_BUTTON(priv->checkbox_outgoing_smtp_specific)));
2242         }
2243
2244         display_name = get_entered_account_title (self);
2245         modest_account_settings_set_display_name (priv->settings, display_name);
2246         g_free (display_name);
2247         g_free (provider_id);
2248 }
2249
2250
2251 static void
2252 on_update_model (ModestWizardDialog *dialog)
2253 {
2254         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
2255         save_to_settings (self);
2256
2257 }
2258
2259 static gboolean
2260 on_save (ModestWizardDialog *dialog)
2261 {
2262         ModestEasysetupWizardDialog *self = MODEST_EASYSETUP_WIZARD_DIALOG (dialog);
2263         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2264
2265         save_to_settings (self);
2266
2267         if (modest_account_mgr_check_already_configured_account (priv->account_manager, priv->settings)) {
2268                 modest_platform_information_banner (NULL, NULL, _("mail_ib_setting_failed"));
2269                 return FALSE;
2270         }
2271
2272         return modest_account_mgr_add_account_from_settings (priv->account_manager, priv->settings);
2273
2274 }
2275
2276
2277 static GList*
2278 check_for_supported_auth_methods (ModestEasysetupWizardDialog* self)
2279 {
2280         GError *error = NULL;
2281         ModestProtocolType protocol_type;
2282         const gchar* hostname;
2283         const gchar* username;
2284         ModestProtocolType security_protocol_incoming_type;
2285         ModestProtocolRegistry *registry;
2286         int port_num;
2287         GList *list_auth_methods;
2288         ModestEasysetupWizardDialogPrivate *priv;
2289         
2290         priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2291         registry = modest_runtime_get_protocol_registry ();
2292         protocol_type = modest_servertype_picker_get_active_servertype (
2293                 MODEST_SERVERTYPE_PICKER (priv->incoming_servertype_picker));
2294         hostname = gtk_entry_get_text(GTK_ENTRY(priv->entry_incomingserver));
2295         username = gtk_entry_get_text(GTK_ENTRY(priv->entry_user_username));
2296         security_protocol_incoming_type = modest_security_options_view_get_connection_protocol
2297                 (MODEST_SECURITY_OPTIONS_VIEW (priv->incoming_security));
2298         port_num = get_port_from_protocol(protocol_type, FALSE);
2299         list_auth_methods = modest_utils_get_supported_secure_authentication_methods (protocol_type, hostname, port_num,
2300                                                                                       username, GTK_WINDOW (self), &error);
2301
2302         if (list_auth_methods) {
2303                 /* TODO: Select the correct method */
2304                 GList* list = NULL;
2305                 GList* method;
2306                 for (method = list_auth_methods; method != NULL; method = g_list_next(method)) {
2307                         ModestProtocolType auth_protocol_type = (ModestProtocolType) (GPOINTER_TO_INT(method->data));
2308                         if (modest_protocol_registry_protocol_type_has_tag (registry, auth_protocol_type,
2309                                                                             MODEST_PROTOCOL_REGISTRY_SECURE_PROTOCOLS)) {
2310                                 list = g_list_append(list, GINT_TO_POINTER(auth_protocol_type));
2311                         }
2312                 }
2313
2314                 g_list_free(list_auth_methods);
2315
2316                 if (list)
2317                         return list;
2318         }
2319
2320         if(error == NULL || error->domain != modest_utils_get_supported_secure_authentication_error_quark() ||
2321                         error->code != MODEST_UTILS_GET_SUPPORTED_SECURE_AUTHENTICATION_ERROR_CANCELED)
2322         {
2323                 modest_platform_information_banner (GTK_WIDGET(self), NULL,
2324                                                     _("mcen_ib_unableto_discover_auth_methods"));
2325         }
2326
2327         if(error != NULL)
2328                 g_error_free(error);
2329
2330         return NULL;
2331 }
2332
2333 static gboolean 
2334 check_has_supported_auth_methods(ModestEasysetupWizardDialog* self)
2335 {
2336         GList* methods = check_for_supported_auth_methods(self);
2337         if (!methods)
2338         {
2339                 return FALSE;
2340         }
2341
2342         g_list_free(methods);
2343         return TRUE;
2344 }
2345
2346 static gboolean 
2347 check_support_progress_pulse (gpointer userdata)
2348 {
2349         ModestEasysetupWizardDialog *self = (ModestEasysetupWizardDialog *) userdata;
2350         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2351
2352         if (priv->destroyed) {
2353                 priv->check_support_progress_pulse_id = 0;
2354                 return FALSE;
2355         }
2356
2357         gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->check_support_progress));
2358
2359         return TRUE;
2360 }
2361
2362 static gboolean 
2363 check_support_show_progress (gpointer userdata)
2364 {
2365         ModestEasysetupWizardDialog *self = (ModestEasysetupWizardDialog *) userdata;
2366         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2367
2368         priv->check_support_show_progress_id = 0;
2369
2370         if (priv->destroyed)
2371                 return FALSE;
2372
2373         gtk_widget_show (priv->check_support_progress);
2374         gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->check_support_progress));
2375
2376         priv->check_support_progress_pulse_id = g_timeout_add (200, check_support_progress_pulse, self);
2377
2378         return FALSE;
2379 }
2380
2381 static void
2382 check_support_callback (ModestAccountProtocol *protocol,
2383                         gboolean supported,
2384                         gpointer userdata)
2385 {
2386         ModestEasysetupWizardDialog *self = (ModestEasysetupWizardDialog *) userdata;
2387         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2388
2389         priv->pending_check_support --;
2390
2391         if (priv->check_support_show_progress_id > 0) {
2392                 g_source_remove (priv->check_support_show_progress_id);
2393                 priv->check_support_show_progress_id = 0;
2394         }
2395
2396         if (priv->check_support_progress_pulse_id > 0) {
2397                 g_source_remove (priv->check_support_progress_pulse_id);
2398                 priv->check_support_progress_pulse_id = 0;
2399         }
2400
2401         if (priv->pending_check_support == 0) {
2402                 priv->check_support_done = TRUE;
2403
2404                 if (!priv->destroyed) {
2405                         if (priv->presets)
2406                                 fill_providers (self);
2407                         gtk_widget_hide (priv->check_support_progress);
2408                         invoke_enable_buttons_vfunc (self);
2409                 }
2410         }
2411         g_object_unref (self);
2412 }
2413
2414
2415 static void
2416 check_support_of_protocols (ModestEasysetupWizardDialog *self)
2417 {
2418         ModestProtocolRegistry *registry;
2419         GSList *provider_protos, *node;
2420         ModestEasysetupWizardDialogPrivate *priv = MODEST_EASYSETUP_WIZARD_DIALOG_GET_PRIVATE (self);
2421
2422         registry = modest_runtime_get_protocol_registry ();
2423         provider_protos = modest_protocol_registry_get_by_tag (registry, 
2424                                                                MODEST_PROTOCOL_REGISTRY_PROVIDER_PROTOCOLS);
2425
2426         for (node = provider_protos; node != NULL; node = g_slist_next (node)) {
2427                 ModestProtocol *proto = MODEST_PROTOCOL (node->data);
2428
2429                 if (!modest_protocol_registry_protocol_type_has_tag (registry, 
2430                                                                      modest_protocol_get_type_id (proto),
2431                                                                      MODEST_PROTOCOL_REGISTRY_STORE_PROTOCOLS))
2432                         continue;
2433
2434                 if (modest_protocol_registry_protocol_type_has_tag 
2435                     (registry,
2436                      modest_protocol_get_type_id (proto),
2437                      MODEST_PROTOCOL_REGISTRY_SINGLETON_PROVIDER_PROTOCOLS)) {
2438                         /* Check if there's already an account configured with this account type */
2439                         if (modest_account_mgr_singleton_protocol_exists (modest_runtime_get_account_mgr (),
2440                                                                           modest_protocol_get_type_id (proto)))
2441                                 continue;
2442                 }
2443
2444                 if (MODEST_ACCOUNT_PROTOCOL (proto)) {
2445                         priv->pending_check_support ++;
2446                         modest_account_protocol_check_support (MODEST_ACCOUNT_PROTOCOL (proto),
2447                                                                check_support_callback,
2448                                                                g_object_ref (self));
2449                 }
2450         }
2451         g_slist_free (provider_protos);
2452
2453         if (priv->pending_check_support > 0) {
2454                 priv->check_support_show_progress_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 1000,
2455                                                                            check_support_show_progress, 
2456                                                                            g_object_ref (self), g_object_unref);
2457         } else {
2458                 priv->check_support_done = TRUE;
2459         }
2460         invoke_enable_buttons_vfunc (self);
2461 }