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