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