Modest executes again in GNOME :-)
[modest] / src / gnome / modest-default-account-settings-dialog.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 #include "widgets/modest-account-settings-dialog.h"
32 #include <glib/gi18n.h>
33 #include <gtk/gtknotebook.h>
34 #include <gtk/gtkvbox.h>
35 #include <gtk/gtklabel.h>
36 #include <gtk/gtkcombobox.h>
37 #include <gtk/gtkentry.h>
38 #include <gtk/gtkbutton.h>
39 #include <gtk/gtkcheckbutton.h>
40 #include <gtk/gtkmessagedialog.h>
41 #include <gtk/gtkstock.h>
42
43 #include "widgets/modest-serversecurity-combo-box.h"
44 #include "widgets/modest-secureauth-combo-box.h"
45 #include "widgets/modest-validating-entry.h"
46 #include "widgets/modest-retrieve-combo-box.h"
47 #include "widgets/modest-limit-retrieve-combo-box.h"
48 #include "modest-defs.h"
49 #include "modest-text-utils.h"
50 #include "modest-account-mgr.h"
51 #include "modest-account-mgr-helpers.h" /* For modest_account_mgr_get_account_data(). */
52 #include "modest-runtime.h" /* For modest_runtime_get_account_mgr(). */
53 #include "modest-protocol-registry.h"
54 #include <modest-utils.h>
55 #include <modest-platform.h>
56 #include "widgets/modest-ui-constants.h"
57 #include "widgets/modest-default-account-settings-dialog.h"
58 #include <tny-account.h>
59 #include <tny-status.h>
60 #include <tny-simple-list.h>
61
62 #include <gconf/gconf-client.h>
63 #include <string.h> /* For strlen(). */
64
65 /* Include config.h so that _() works: */
66 #ifdef HAVE_CONFIG_H
67 #include <config.h>
68 #endif
69
70 #define PORT_MIN 1
71 #define PORT_MAX 65535
72
73 static void modest_account_settings_dialog_init (gpointer g, gpointer iface_data);
74
75 G_DEFINE_TYPE_EXTENDED (ModestDefaultAccountSettingsDialog, 
76                         modest_default_account_settings_dialog, 
77                         GTK_TYPE_DIALOG,
78                         0, 
79                         G_IMPLEMENT_INTERFACE (MODEST_TYPE_ACCOUNT_SETTINGS_DIALOG, 
80                                                modest_account_settings_dialog_init));
81
82 #define MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE(o) \
83         (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
84                                       MODEST_TYPE_DEFAULT_ACCOUNT_SETTINGS_DIALOG, \
85                                       ModestDefaultAccountSettingsDialogPrivate))
86
87 typedef struct _ModestDefaultAccountSettingsDialogPrivate ModestDefaultAccountSettingsDialogPrivate;
88
89 struct _ModestDefaultAccountSettingsDialogPrivate
90 {
91         /* Used by derived widgets to query existing accounts,
92          * and to create new accounts: */
93         ModestAccountMgr *account_manager;
94         ModestAccountSettings *settings;
95         
96         gboolean modified;
97         gchar * account_name; /* This may not change. It is not user visible. */
98         ModestProtocolType incoming_protocol; /* This may not change. */
99         ModestProtocolType outgoing_protocol; /* This may not change. */
100         gchar * original_account_title;
101
102         ModestProtocolType protocol_authentication_incoming;
103         
104         GtkNotebook *notebook;
105         
106         GtkWidget *page_account_details;
107         GtkWidget *entry_account_title;
108         GtkWidget *combo_retrieve;
109         GtkWidget *combo_limit_retrieve;
110         GtkWidget *caption_leave_messages;
111         GtkWidget *checkbox_leave_messages;
112         
113         GtkWidget *page_user_details;
114         GtkWidget *entry_user_name;
115         GtkWidget *entry_user_username;
116         GtkWidget *entry_user_password;
117         GtkWidget *entry_user_email;
118         GtkWidget *entry_incoming_port;
119         GtkWidget *button_signature;
120         
121         GtkWidget *page_complete_easysetup;
122         
123         GtkWidget *page_incoming;
124         GtkWidget *caption_incoming;
125         GtkWidget *entry_incomingserver;
126         GtkWidget *combo_incoming_security;
127         GtkWidget *checkbox_incoming_auth;
128
129         GtkWidget *page_outgoing;
130         GtkWidget *entry_outgoingserver;
131         GtkWidget *caption_outgoing_username;
132         GtkWidget *entry_outgoing_username;
133         GtkWidget *caption_outgoing_password;
134         GtkWidget *entry_outgoing_password;
135         GtkWidget *combo_outgoing_security;
136         GtkWidget *combo_outgoing_auth;
137         GtkWidget *entry_outgoing_port;
138         GtkWidget *checkbox_outgoing_smtp_specific;
139         GtkWidget *button_outgoing_smtp_servers;
140         
141         GtkWidget *signature_dialog;
142 };
143
144 static void enable_buttons (ModestAccountSettingsDialog *self);
145 static gboolean save_configuration (ModestAccountSettingsDialog *dialog);
146 static void modest_default_account_settings_dialog_load_settings (ModestAccountSettingsDialog *dialog, 
147                                                                   ModestAccountSettings *settings);
148
149 static const gchar *
150 null_means_empty (const gchar * str)
151 {
152         return str ? str : "";
153 }
154
155
156 static void
157 modest_account_settings_dialog_get_property (GObject *object, guint property_id,
158                                                                                                                         GValue *value, GParamSpec *pspec)
159 {
160         switch (property_id) {
161         default:
162                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
163         }
164 }
165
166 static void
167 modest_account_settings_dialog_set_property (GObject *object, guint property_id,
168                                                                                                                         const GValue *value, GParamSpec *pspec)
169 {
170         switch (property_id) {
171         default:
172                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
173         }
174 }
175
176 static void
177 modest_account_settings_dialog_dispose (GObject *object)
178 {
179         if (G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->dispose)
180                 G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->dispose (object);
181 }
182
183 static void
184 modest_account_settings_dialog_finalize (GObject *object)
185 {
186         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (object);
187         ModestDefaultAccountSettingsDialogPrivate *priv;
188
189         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
190         
191         if (priv->account_name)
192                 g_free (priv->account_name);
193                 
194         if (priv->original_account_title)
195                 g_free (priv->original_account_title);
196                 
197         if (priv->account_manager)
198                 g_object_unref (G_OBJECT (priv->account_manager));
199                 
200         if (priv->signature_dialog)
201                 gtk_widget_destroy (priv->signature_dialog);
202
203         if (priv->settings) {
204                 g_object_unref (priv->settings);
205                 priv->settings = NULL;
206         }
207         
208         G_OBJECT_CLASS (modest_default_account_settings_dialog_parent_class)->finalize (object);
209 }
210
211 static void
212 on_combo_incoming_security_changed (GtkComboBox *widget, gpointer user_data);
213
214 static void
215 on_combo_outgoing_security_changed (GtkComboBox *widget, gpointer user_data);
216
217 static void
218 on_modified_combobox_changed (GtkComboBox *widget, gpointer user_data)
219 {
220         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
221         ModestDefaultAccountSettingsDialogPrivate *priv;
222
223         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
224         priv->modified = TRUE;
225 }
226
227 static void
228 on_modified_entry_changed (GtkEditable *editable, gpointer user_data)
229 {
230         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
231         ModestDefaultAccountSettingsDialogPrivate *priv;
232
233         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
234         priv->modified = TRUE;
235 }
236
237 static void
238 on_modified_checkbox_toggled (GtkToggleButton *togglebutton, gpointer user_data)
239 {
240         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
241         ModestDefaultAccountSettingsDialogPrivate *priv;
242
243         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
244         priv->modified = TRUE;
245 }
246
247 static void
248 on_modified_spin_button_changed (GtkSpinButton *spin_button, gpointer user_data)
249 {
250         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
251         ModestDefaultAccountSettingsDialogPrivate *priv;
252
253         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
254         gint value = gtk_spin_button_get_value_as_int (spin_button);
255
256         gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_OK, value > 0);
257         priv->modified = TRUE;
258 }
259
260 /* Set a modified boolean whenever the widget is changed, 
261  * so we can check for it later.
262  */
263 static void
264 connect_for_modified (ModestDefaultAccountSettingsDialog *self, 
265                       GtkWidget *widget)
266 {
267         if (GTK_SPIN_BUTTON (widget)) {
268                 g_signal_connect (G_OBJECT (widget), "value_changed",
269                         G_CALLBACK (on_modified_spin_button_changed), self);
270         }
271         else if (GTK_IS_ENTRY (widget)) {
272                 g_signal_connect (G_OBJECT (widget), "changed",
273                         G_CALLBACK (on_modified_entry_changed), self);
274         } else if (GTK_IS_COMBO_BOX (widget)) {
275                 g_signal_connect (G_OBJECT (widget), "changed",
276                         G_CALLBACK (on_modified_combobox_changed), self);       
277         } else if (GTK_IS_TOGGLE_BUTTON (widget)) {
278                 g_signal_connect (G_OBJECT (widget), "toggled",
279                         G_CALLBACK (on_modified_checkbox_toggled), self);
280         }
281 }
282
283 static void
284 on_field_entry_changed (GtkEditable *editable, gpointer user_data)
285 {
286         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
287         g_assert(self);
288         enable_buttons(self);
289 }
290
291 static void
292 on_field_combobox_changed (GtkComboBox *widget, gpointer user_data)
293 {
294         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
295         g_assert(self);
296         enable_buttons(self);
297 }
298
299 /** This is a convenience function to create a field containing a mandatory widget.
300  * When the widget is edited, the enable_buttons() vfunc will be called.
301  */
302 static GtkWidget* 
303 create_field(ModestDefaultAccountSettingsDialog *self,
304              GtkSizeGroup *group,
305              const gchar *value,
306              GtkWidget *control,
307              GtkWidget *icon,
308              gboolean mandatory)
309 {
310         GtkWidget *hbox;
311         gchar *title;
312         GtkWidget *label;
313
314         hbox = gtk_hbox_new (FALSE, 12);
315         if (mandatory)
316                 title = g_strdup_printf("%s*:", value);
317         else
318                 title = g_strdup_printf ("%s:", value);
319         label = gtk_label_new (title);
320         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
321         g_free (title);
322
323         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
324         gtk_box_pack_start (GTK_BOX (hbox), control, TRUE, TRUE, 0);
325         gtk_size_group_add_widget (group, label);
326   
327         /* Connect to the appropriate changed signal for the widget, 
328          * so we can ask for the prev/next buttons to be enabled/disabled appropriately:
329          */
330         if (GTK_IS_ENTRY (control)) {
331                 g_signal_connect (G_OBJECT (control), "changed",
332                 G_CALLBACK (on_field_entry_changed), self);
333                 
334         }
335         else if (GTK_IS_COMBO_BOX (control)) {
336                 g_signal_connect (G_OBJECT (control), "changed",
337                 G_CALLBACK (on_field_combobox_changed), self);
338         }
339         gtk_widget_show_all (hbox);
340          
341         return hbox;
342 }
343
344 static void
345 on_entry_invalid_account_title_character (ModestValidatingEntry *self, const gchar* character, gpointer user_data)
346 {
347         gchar *tmp, *msg;
348                         
349         tmp = g_strndup (account_title_forbidden_chars, ACCOUNT_TITLE_FORBIDDEN_CHARS_LENGTH);
350         msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
351
352         modest_platform_information_banner (GTK_WIDGET (self), NULL, msg);
353
354         g_free (msg);
355         g_free (tmp);
356 }
357
358 static void
359 on_entry_invalid_fullname_character (ModestValidatingEntry *self, const gchar* character, gpointer user_data)
360 {
361         gchar *tmp, *msg;
362                         
363         tmp = g_strndup (user_name_forbidden_chars, USER_NAME_FORBIDDEN_CHARS_LENGTH);
364         msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
365
366         modest_platform_information_banner(GTK_WIDGET (self), NULL, msg);
367
368         g_free (msg);
369         g_free (tmp);
370 }
371
372
373 static void
374 on_entry_max (ModestValidatingEntry *self, gpointer user_data)
375 {
376         modest_platform_information_banner(GTK_WIDGET (self), NULL, 
377                                          _CS("ckdg_ib_maximum_characters_reached"));
378 }
379
380 static GtkWidget*
381 create_page_account_details (ModestDefaultAccountSettingsDialog *self)
382 {
383         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
384         GtkWidget *alignment;   
385         GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
386         ModestDefaultAccountSettingsDialogPrivate *priv;
387
388         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
389
390         /* The description widgets: */  
391         priv->entry_account_title = GTK_WIDGET (modest_validating_entry_new ());
392         GtkWidget *field = create_field (self, sizegroup, _("mcen_fi_account_title"), 
393                 priv->entry_account_title, NULL, TRUE);
394         gtk_widget_show (priv->entry_account_title);
395         connect_for_modified (self, priv->entry_account_title);
396         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
397         gtk_widget_show (field);
398         
399         /* Prevent the use of some characters in the account title, 
400          * as required by our UI specification: */
401         GList *list_prevent = NULL;
402         list_prevent = g_list_append (list_prevent, "\\");
403         list_prevent = g_list_append (list_prevent, "/");
404         list_prevent = g_list_append (list_prevent, ":");
405         list_prevent = g_list_append (list_prevent, "*");
406         list_prevent = g_list_append (list_prevent, "?");
407         list_prevent = g_list_append (list_prevent, "\"");
408         list_prevent = g_list_append (list_prevent, "<"); 
409         list_prevent = g_list_append (list_prevent, ">"); 
410         list_prevent = g_list_append (list_prevent, "|");
411         list_prevent = g_list_append (list_prevent, "^");       
412         modest_validating_entry_set_unallowed_characters (
413                 MODEST_VALIDATING_ENTRY (priv->entry_account_title), list_prevent);
414         g_list_free (list_prevent);
415         modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_account_title),
416                                          on_entry_invalid_account_title_character, self);
417         
418         /* Set max length as in the UI spec:
419          * The UI spec seems to want us to show a dialog if we hit the maximum. */
420         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_account_title), 64);
421         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_account_title), 
422                 on_entry_max, self);
423         
424         /* The retrieve combobox: */
425         priv->combo_retrieve = GTK_WIDGET (modest_retrieve_combo_box_new ());
426         field = create_field (self, sizegroup, _("mcen_fi_advsetup_retrievetype"), 
427                               priv->combo_retrieve, NULL, TRUE);
428         gtk_widget_show (priv->combo_retrieve);
429         connect_for_modified (self, priv->combo_retrieve);
430         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
431         gtk_widget_show (field);
432         
433         /* The limit-retrieve combobox: */
434         priv->combo_limit_retrieve = GTK_WIDGET (modest_limit_retrieve_combo_box_new ());
435         field = create_field (self, sizegroup, _("mcen_fi_advsetup_limit_retrieve"), 
436                               priv->combo_limit_retrieve, NULL, TRUE);
437         gtk_widget_show (priv->combo_limit_retrieve);
438         connect_for_modified (self, priv->combo_limit_retrieve);
439         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
440         gtk_widget_show (field);
441
442         /* The leave-messages widgets: */
443         if(!priv->checkbox_leave_messages)
444                 priv->checkbox_leave_messages = gtk_check_button_new ();
445         if (!priv->caption_leave_messages) {
446                 priv->caption_leave_messages = create_field (self, sizegroup, _("mcen_fi_advsetup_leave_on_server"), 
447                                                              priv->checkbox_leave_messages, NULL, TRUE);
448         }
449                         
450         gtk_widget_show (priv->checkbox_leave_messages);
451         connect_for_modified (self, priv->checkbox_leave_messages);
452         gtk_box_pack_start (GTK_BOX (box), priv->caption_leave_messages, FALSE, FALSE, MODEST_MARGIN_HALF);
453         gtk_widget_show (priv->caption_leave_messages);
454         
455         gtk_widget_show (GTK_WIDGET (box));
456
457         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
458         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 12, 12);
459         gtk_container_add (GTK_CONTAINER (alignment), box);
460         gtk_widget_show (alignment);
461         
462         return GTK_WIDGET (alignment);
463 }
464
465 static gchar*
466 get_entered_account_title (ModestAccountSettingsDialog *dialog)
467 {
468         ModestDefaultAccountSettingsDialogPrivate *priv;
469
470         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
471
472         const gchar* account_title = 
473                 gtk_entry_get_text (GTK_ENTRY (priv->entry_account_title));
474         if (!account_title || (strlen (account_title) == 0))
475                 return NULL;
476         else {
477                 /* Strip it of whitespace at the start and end: */
478                 gchar *result = g_strdup (account_title);
479                 result = g_strstrip (result);
480                 
481                 if (!result)
482                         return NULL;
483                         
484                 if (strlen (result) == 0) {
485                         g_free (result);
486                         return NULL;    
487                 }
488                 
489                 return result;
490         }
491 }
492
493
494 static void
495 on_button_signature (GtkButton *button, gpointer user_data)
496 {
497 /*      ModestAccountSettingsDialog * self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data); */
498         
499 /*      /\* Create the window, if necessary: *\/ */
500 /*      if (!(priv->signature_dialog)) { */
501 /*              priv->signature_dialog = GTK_WIDGET (modest_signature_editor_dialog_new ()); */
502         
503 /*              gboolean use_signature = modest_account_settings_get_use_signature (priv->settings); */
504 /*              const gchar *signature = modest_account_settings_get_signature(priv->settings); */
505 /*              gchar* account_title = get_entered_account_title (self); */
506 /*              modest_signature_editor_dialog_set_settings ( */
507 /*                      MODEST_SIGNATURE_EDITOR_DIALOG (priv->signature_dialog),  */
508 /*                      use_signature, signature, account_title); */
509
510 /*              g_free (account_title); */
511 /*              account_title = NULL; */
512 /*              signature = NULL; */
513 /*      } */
514
515 /*      /\* Show the window: *\/         */
516 /*      gtk_window_set_transient_for (GTK_WINDOW (priv->signature_dialog), GTK_WINDOW (self)); */
517 /*      gtk_window_set_modal (GTK_WINDOW (priv->signature_dialog), TRUE); */
518 /*     const gint response = gtk_dialog_run (GTK_DIALOG (priv->signature_dialog)); */
519 /*     gtk_widget_hide (priv->signature_dialog); */
520 /*     if (response != GTK_RESPONSE_OK) { */
521 /*      /\* Destroy the widget now, and its data: *\/ */
522 /*      gtk_widget_destroy (priv->signature_dialog); */
523 /*      priv->signature_dialog = NULL; */
524 /*     } */
525 /*     else { */
526 /*      /\* Mark modified, so we use the dialog's data later: *\/ */
527 /*      priv->modified = TRUE;   */
528 /*     } */
529 }
530
531 static GtkWidget*
532 create_page_user_details (ModestDefaultAccountSettingsDialog *self)
533 {
534         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
535         GtkWidget *alignment;   
536         GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
537         ModestDefaultAccountSettingsDialogPrivate *priv;
538
539         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
540          
541         /* The name widgets: */
542         priv->entry_user_name = GTK_WIDGET (modest_validating_entry_new ());
543
544         /* Set max length as in the UI spec:
545          * The UI spec seems to want us to show a dialog if we hit the maximum. */
546         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_name), 64);
547         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_name), 
548                 on_entry_max, self);
549         GtkWidget *field = create_field (self, sizegroup, 
550                                          _("mcen_li_emailsetup_name"), priv->entry_user_name, NULL, FALSE);
551         gtk_widget_show (priv->entry_user_name);
552         connect_for_modified (self, priv->entry_user_name);
553         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
554         gtk_widget_show (field);
555
556
557         /* Prevent the use of some characters in the name, 
558          * as required by our UI specification: */
559         GList *list_prevent = NULL;
560         list_prevent = g_list_append (list_prevent, "<");
561         list_prevent = g_list_append (list_prevent, ">");
562         modest_validating_entry_set_unallowed_characters (
563                 MODEST_VALIDATING_ENTRY (priv->entry_user_name), list_prevent);
564         g_list_free (list_prevent);
565         modest_validating_entry_set_func(MODEST_VALIDATING_ENTRY(priv->entry_user_name),
566                                          on_entry_invalid_fullname_character, self);
567         
568         /* The username widgets: */     
569         priv->entry_user_username = GTK_WIDGET (modest_validating_entry_new ());
570         field = create_field (self, sizegroup, _("mail_fi_username"), 
571                                 priv->entry_user_username, NULL, TRUE);
572         gtk_widget_show (priv->entry_user_username);
573         connect_for_modified (self, priv->entry_user_username);
574         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
575         gtk_widget_show (field);
576         
577         /* Prevent the use of some characters in the username, 
578          * as required by our UI specification: */
579         modest_validating_entry_set_unallowed_characters_whitespace (
580                 MODEST_VALIDATING_ENTRY (priv->entry_user_username));
581         
582         /* Set max length as in the UI spec:
583          * The UI spec seems to want us to show a dialog if we hit the maximum. */
584         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_username), 64);
585         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_username), 
586                 on_entry_max, self);
587         
588         /* The password widgets: */     
589         priv->entry_user_password = gtk_entry_new ();
590         gtk_entry_set_visibility (GTK_ENTRY (priv->entry_user_password), FALSE);
591         /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_user_password), '*'); */
592         field = create_field (self, sizegroup, 
593                               _("mail_fi_password"), priv->entry_user_password, NULL, FALSE);
594         gtk_widget_show (priv->entry_user_password);
595         connect_for_modified (self, priv->entry_user_password);
596         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
597         gtk_widget_show (field);
598         
599         /* The email address widgets: */        
600         priv->entry_user_email = GTK_WIDGET (modest_validating_entry_new ());
601         field = create_field (self, sizegroup, 
602                               _("mcen_li_emailsetup_email_address"), priv->entry_user_email, NULL, TRUE);
603         gtk_entry_set_text (GTK_ENTRY (priv->entry_user_email), MODEST_EXAMPLE_EMAIL_ADDRESS); /* Default text. */
604         gtk_widget_show (priv->entry_user_email);
605         connect_for_modified (self, priv->entry_user_email);
606         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
607         gtk_widget_show (field);
608         
609         /* Set max length as in the UI spec:
610          * The UI spec seems to want us to show a dialog if we hit the maximum. */
611         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_user_email), 64);
612         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_user_email), 
613                 on_entry_max, self);
614         
615         /* Signature button: */
616         if (!priv->button_signature)
617                 priv->button_signature = gtk_button_new_with_label (_("mcen_bd_edit"));
618         field = create_field (self, sizegroup, _("mcen_fi_email_signature"), 
619                 priv->button_signature, NULL, FALSE);
620         gtk_widget_show (priv->button_signature);
621         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
622         gtk_widget_show (field);
623                 
624         g_signal_connect (G_OBJECT (priv->button_signature), "clicked",
625                 G_CALLBACK (on_button_signature), self);
626                 
627         gtk_widget_show (GTK_WIDGET (box));
628
629         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
630         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 12, 12);
631         gtk_container_add (GTK_CONTAINER (alignment), box);
632         gtk_widget_show (alignment);
633         
634         return GTK_WIDGET (alignment);
635 }
636
637 /** Change the field title for the incoming server, 
638  * as specified in the UI spec:
639  */
640 static void 
641 update_incoming_server_title (ModestAccountSettingsDialog *self, 
642                               ModestProtocolType protocol)
643 {
644         ModestDefaultAccountSettingsDialogPrivate *priv;
645
646         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
647
648         const gchar* type = 
649                 (protocol == MODEST_PROTOCOLS_STORE_POP ? 
650                         _("mail_fi_emailtype_pop3") : 
651                         _("mail_fi_emailtype_imap") );
652                         
653                 
654         /* Note that this produces a compiler warning, 
655          * because the compiler does not know that the translated string will have a %s in it.
656          * I do not see a way to avoid the warning while still using these Logical IDs. murrayc. */
657         gchar* incomingserver_title = g_strdup_printf(_("mcen_li_emailsetup_servertype"), type);
658         
659         /* This is a mandatory field, so add a *. This is usually done by 
660          * create_field() but we can't use that here. */
661         gchar *with_asterisk = g_strconcat (incomingserver_title, "*", NULL);
662         g_free (incomingserver_title);
663         
664         g_object_set (G_OBJECT (priv->caption_incoming), "label", with_asterisk, NULL);
665         g_free(with_asterisk);
666 }
667
668 /** Change the field title for the incoming server, 
669  * as specified in the UI spec:
670  */
671 static void 
672 update_incoming_server_security_choices (ModestAccountSettingsDialog *self, 
673                                          ModestProtocolType protocol)
674 {
675         ModestDefaultAccountSettingsDialogPrivate *priv;
676
677         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
678
679         /* Fill the combo with appropriately titled choices for POP or IMAP. */
680         /* The choices are the same, but the titles are different, as in the UI spec. */
681         modest_serversecurity_combo_box_fill (
682                 MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security), protocol);
683 }
684            
685 static GtkWidget* 
686 create_page_incoming (ModestDefaultAccountSettingsDialog *self)
687 {
688         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
689         GtkWidget *alignment;
690         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
691         ModestDefaultAccountSettingsDialogPrivate *priv;
692
693         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
694          
695         /* The incoming server widgets: */
696         if(!priv->entry_incomingserver)
697                 priv->entry_incomingserver = gtk_entry_new ();
698
699         if (priv->caption_incoming)
700           gtk_widget_destroy (priv->caption_incoming);
701            
702         /* The field title will be updated in update_incoming_server_title().
703          * so this default text will never be seen: */
704         /* (Note: Changing the title seems pointless. murrayc) */
705         priv->caption_incoming = create_field (self, sizegroup, 
706                                              "Incoming Server", priv->entry_incomingserver, NULL, TRUE);
707         gtk_widget_show (priv->entry_incomingserver);
708         connect_for_modified (self, priv->entry_incomingserver);
709         gtk_box_pack_start (GTK_BOX (box), priv->caption_incoming, FALSE, FALSE, MODEST_MARGIN_HALF);
710         gtk_widget_show (priv->caption_incoming);
711         
712         /* The secure connection widgets: */
713         /* This will be filled by update_incoming_server_security_choices(). */
714         if (!priv->combo_incoming_security)
715                 priv->combo_incoming_security = GTK_WIDGET (modest_serversecurity_combo_box_new ());
716         GtkWidget *field = create_field (self, sizegroup, _("mcen_li_emailsetup_secure_connection"), 
717                                          priv->combo_incoming_security, NULL, FALSE);
718         gtk_widget_show (priv->combo_incoming_security);
719         connect_for_modified (self, priv->combo_incoming_security);
720         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
721         gtk_widget_show (field);
722         
723         /* Show a default port number when the security method changes, as per the UI spec: */
724         g_signal_connect (G_OBJECT (priv->combo_incoming_security), "changed", (GCallback)on_combo_incoming_security_changed, self);
725         
726         
727         /* The port widgets: */
728         if (!priv->entry_incoming_port)
729                 priv->entry_incoming_port = GTK_WIDGET (gtk_spin_button_new_with_range ((gdouble) PORT_MIN, (gdouble) PORT_MAX, 1.0));
730         field = create_field (self, sizegroup, _("mcen_fi_emailsetup_port"), 
731                 priv->entry_incoming_port, NULL, FALSE);
732         gtk_widget_show (priv->entry_incoming_port);
733         connect_for_modified (self, priv->entry_incoming_port);
734         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
735         gtk_widget_show (field);
736         
737         /* The secure authentication widgets: */
738         if(!priv->checkbox_incoming_auth)
739                 priv->checkbox_incoming_auth = gtk_check_button_new ();
740         field = create_field (self, sizegroup, _("mcen_li_emailsetup_secure_authentication"), 
741                               priv->checkbox_incoming_auth, NULL, FALSE);
742         gtk_widget_show (priv->checkbox_incoming_auth);
743         connect_for_modified (self, priv->checkbox_incoming_auth);
744         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
745         gtk_widget_show (field);
746         
747         gtk_widget_show (GTK_WIDGET (box));
748         
749         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
750         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 12, 12);
751         gtk_container_add (GTK_CONTAINER (alignment), box);
752         gtk_widget_show (alignment);
753         
754         return GTK_WIDGET (alignment);
755 }
756
757 static void
758 on_toggle_button_changed (GtkToggleButton *togglebutton, gpointer user_data)
759 {
760         GtkWidget *widget = GTK_WIDGET (user_data);
761         
762         /* Enable the widget only if the toggle button is active: */
763         const gboolean enable = gtk_toggle_button_get_active (togglebutton);
764         gtk_widget_set_sensitive (widget, enable);
765 }
766
767 /* Make the sensitivity of a widget depend on a toggle button.
768  */
769 static void
770 enable_widget_for_togglebutton (GtkWidget *widget, GtkToggleButton* button)
771 {
772         g_signal_connect (G_OBJECT (button), "toggled",
773                 G_CALLBACK (on_toggle_button_changed), widget);
774         
775         /* Set the starting sensitivity: */
776         on_toggle_button_changed (button, widget);
777 }
778
779 static void
780 on_button_outgoing_smtp_servers (GtkButton *button, gpointer user_data)
781 {
782 /*      ModestAccountSettingsDialog * self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data); */
783         
784 /*      /\* Create the window if necessary: *\/ */
785 /*      if (!(priv->specific_window)) { */
786 /*              priv->specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ()); */
787 /*              modest_connection_specific_smtp_window_fill_with_connections ( */
788 /*                      MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (priv->specific_window), priv->account_manager); */
789 /*      } */
790
791 /*      /\* Show the window: *\/         */
792 /*      gtk_window_set_transient_for (GTK_WINDOW (priv->specific_window), GTK_WINDOW (self)); */
793 /*      gtk_window_set_modal (GTK_WINDOW (priv->specific_window), TRUE); */
794 /*      gtk_widget_show (priv->specific_window); */
795 /*      priv->modified = TRUE; */
796 }
797
798 static void
799 on_combo_outgoing_auth_changed (GtkComboBox *widget, gpointer user_data)
800 {
801         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
802         ModestDefaultAccountSettingsDialogPrivate *priv;
803
804         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
805         
806         ModestProtocolType protocol_security = 
807                 modest_secureauth_combo_box_get_active_secureauth (
808                         MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth));
809         const gboolean secureauth_used = protocol_security != MODEST_PROTOCOLS_AUTH_NONE;
810         
811         gtk_widget_set_sensitive (priv->caption_outgoing_username, secureauth_used);
812         gtk_widget_set_sensitive (priv->caption_outgoing_password, secureauth_used);
813 }
814
815 static void
816 on_combo_outgoing_security_changed (GtkComboBox *widget, gpointer user_data)
817 {
818         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
819         ModestDefaultAccountSettingsDialogPrivate *priv;
820
821         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
822         
823         const gint port_number = 
824                 modest_serversecurity_combo_box_get_active_serversecurity_port (
825                         MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security));
826
827         if(port_number != 0) {
828                 gtk_spin_button_set_value (
829                         GTK_SPIN_BUTTON (priv->entry_outgoing_port), (gdouble) port_number);
830         }               
831 }
832
833 static void
834 on_combo_incoming_security_changed (GtkComboBox *widget, gpointer user_data)
835 {
836         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
837         ModestDefaultAccountSettingsDialogPrivate *priv;
838
839         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
840
841         const gint port_number = 
842                 modest_serversecurity_combo_box_get_active_serversecurity_port (
843                         MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security));
844
845         if(port_number != 0) {
846                 gtk_spin_button_set_value (
847                         GTK_SPIN_BUTTON (priv->entry_incoming_port), (gdouble) port_number);
848         }               
849 }
850
851
852 static GtkWidget* 
853 create_page_outgoing (ModestDefaultAccountSettingsDialog *self)
854 {
855         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_NONE);
856         GtkWidget *alignment;
857         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
858
859         ModestDefaultAccountSettingsDialogPrivate *priv;
860
861         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
862          
863         /* The outgoing server widgets: */
864         if (!priv->entry_outgoingserver)
865                 priv->entry_outgoingserver = gtk_entry_new ();
866         GtkWidget *field = create_field (self, sizegroup, 
867                                          _("mcen_li_emailsetup_smtp"), priv->entry_outgoingserver, NULL, FALSE);
868         gtk_widget_show (priv->entry_outgoingserver);
869         connect_for_modified (self, priv->entry_outgoingserver);
870         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
871         gtk_widget_show (field);
872         
873         /* The secure authentication widgets: */
874         if (!priv->combo_outgoing_auth)
875                 priv->combo_outgoing_auth = GTK_WIDGET (modest_secureauth_combo_box_new ());
876         field = create_field (self, sizegroup, _("mcen_li_emailsetup_secure_authentication"), 
877                 priv->combo_outgoing_auth, NULL, FALSE);
878         gtk_widget_show (priv->combo_outgoing_auth);
879         connect_for_modified (self, priv->combo_outgoing_auth);
880         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
881         gtk_widget_show (field);
882         
883         /* Dim the outgoing username and password when no secure authentication is used, as per the UI spec: */
884         g_signal_connect (G_OBJECT (priv->combo_outgoing_auth), "changed", (GCallback)on_combo_outgoing_auth_changed, self);
885         
886         /* The username widgets: */     
887         priv->entry_outgoing_username = GTK_WIDGET (modest_validating_entry_new ());
888         priv->caption_outgoing_username = create_field (self, sizegroup, _("mail_fi_username"), 
889                                                       priv->entry_outgoing_username, NULL, TRUE);
890         gtk_widget_show (priv->entry_outgoing_username);
891         connect_for_modified (self, priv->entry_outgoing_username);
892         gtk_box_pack_start (GTK_BOX (box), priv->caption_outgoing_username, FALSE, FALSE, MODEST_MARGIN_HALF);
893         gtk_widget_show (priv->caption_outgoing_username);
894         
895         /* Prevent the use of some characters in the username, 
896          * as required by our UI specification: */
897         modest_validating_entry_set_unallowed_characters_whitespace (
898                 MODEST_VALIDATING_ENTRY (priv->entry_outgoing_username));
899         
900         /* Set max length as in the UI spec:
901          * The UI spec seems to want us to show a dialog if we hit the maximum. */
902         gtk_entry_set_max_length (GTK_ENTRY (priv->entry_outgoing_username), 64);
903         modest_validating_entry_set_max_func (MODEST_VALIDATING_ENTRY (priv->entry_outgoing_username), 
904                 on_entry_max, self);
905                 
906         /* The password widgets: */     
907         priv->entry_outgoing_password = gtk_entry_new ();
908         gtk_entry_set_visibility (GTK_ENTRY (priv->entry_outgoing_password), FALSE);
909         /* gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry_outgoing_password), '*'); */
910         priv->caption_outgoing_password = create_field (self, sizegroup, 
911                                                       _("mail_fi_password"), priv->entry_outgoing_password, NULL, FALSE);
912         gtk_widget_show (priv->entry_outgoing_password);
913         connect_for_modified (self, priv->entry_outgoing_password);
914         gtk_box_pack_start (GTK_BOX (box), priv->caption_outgoing_password, FALSE, FALSE, MODEST_MARGIN_HALF);
915         gtk_widget_show (priv->caption_outgoing_password);
916         
917         /* The secure connection widgets: */
918         /* This will be filled and set with modest_serversecurity_combo_box_fill() 
919          * and modest_serversecurity_combo_box_set_active_serversecurity().
920          */
921         if (!priv->combo_outgoing_security)
922                 
923                 priv->combo_outgoing_security = GTK_WIDGET (modest_serversecurity_combo_box_new ());
924         field = create_field (self, sizegroup, _("mcen_li_emailsetup_secure_connection"), 
925                               priv->combo_outgoing_security, NULL, FALSE);
926         gtk_widget_show (priv->combo_outgoing_security);
927         connect_for_modified (self, priv->combo_outgoing_security);
928         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
929         gtk_widget_show (field);
930         
931         /* Show a default port number when the security method changes, as per the UI spec: */
932         g_signal_connect (G_OBJECT (priv->combo_outgoing_security), "changed", (GCallback)on_combo_outgoing_security_changed, self);
933         
934         /* The port widgets: */
935         if (!priv->entry_outgoing_port)
936                 priv->entry_outgoing_port = GTK_WIDGET (gtk_spin_button_new_with_range ((gdouble)PORT_MIN, (gdouble) PORT_MAX, 1.0));
937         field = create_field (self, sizegroup, _("mcen_fi_emailsetup_port"), 
938                               priv->entry_outgoing_port, NULL, FALSE);
939         gtk_widget_show (priv->entry_outgoing_port);
940         connect_for_modified (self, priv->entry_outgoing_port);
941         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
942         gtk_widget_show (field);
943         
944         GtkWidget *separator = gtk_hseparator_new ();
945         gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, MODEST_MARGIN_HALF);
946         gtk_widget_show (separator);
947         
948         /* connection-specific checkbox: */
949         if (!priv->checkbox_outgoing_smtp_specific) {
950                 priv->checkbox_outgoing_smtp_specific = gtk_check_button_new ();
951                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific), 
952                         FALSE);
953         }
954         field = create_field (self, sizegroup, _("mcen_fi_advsetup_connection_smtp"), 
955                               priv->checkbox_outgoing_smtp_specific, NULL, FALSE);
956         gtk_widget_show (priv->checkbox_outgoing_smtp_specific);
957         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
958         gtk_widget_show (field);
959         connect_for_modified (self, priv->checkbox_outgoing_smtp_specific);
960         
961         /* Connection-specific SMTP-Severs Edit button: */
962         if (!priv->button_outgoing_smtp_servers)
963                 priv->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_edit"));
964         field = create_field (self, sizegroup, _("mcen_fi_advsetup_optional_smtp"), 
965                               priv->button_outgoing_smtp_servers, NULL, FALSE);
966         gtk_widget_show (priv->button_outgoing_smtp_servers);
967         gtk_box_pack_start (GTK_BOX (box), field, FALSE, FALSE, MODEST_MARGIN_HALF);
968         gtk_widget_show (field);
969         
970         /* Only enable the button when the checkbox is checked: */
971         enable_widget_for_togglebutton (priv->button_outgoing_smtp_servers, 
972                 GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific));
973                 
974         g_signal_connect (G_OBJECT (priv->button_outgoing_smtp_servers), "clicked",
975                 G_CALLBACK (on_button_outgoing_smtp_servers), self);
976                 
977         gtk_widget_show (GTK_WIDGET (box));
978         
979         alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
980         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 12, 12);
981         gtk_container_add (GTK_CONTAINER (alignment), box);
982         gtk_widget_show (alignment);
983         
984         return GTK_WIDGET (alignment);
985 }
986         
987 static gboolean
988 check_data (ModestAccountSettingsDialog *self)
989 {
990         ModestDefaultAccountSettingsDialogPrivate *priv;
991
992         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
993
994         /* Check that the title is not already in use: */
995         gchar* account_title = get_entered_account_title (self);
996         if (!account_title)
997                 return FALSE; /* Should be prevented already anyway. */
998                 
999         if (strcmp(account_title, priv->original_account_title) != 0) {
1000                 /* Check the changed title: */
1001                 const gboolean name_in_use  = modest_account_mgr_account_with_display_name_exists (priv->account_manager,
1002                         account_title);
1003         
1004                 if (name_in_use) {
1005                         /* Warn the user via a dialog: */
1006                         modest_platform_information_banner(NULL, NULL, _("mail_ib_account_name_already_existing"));
1007                 
1008                 g_free (account_title);
1009                         return FALSE;
1010                 }
1011         }
1012         
1013         g_free (account_title);
1014         account_title  = NULL;
1015
1016         /* Check that the email address is valid: */
1017         const gchar* email_address = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
1018         if ((!email_address) || (strlen(email_address) == 0)) {
1019                 return FALSE;
1020         }
1021                         
1022         if (!modest_text_utils_validate_email_address (email_address, NULL)) {
1023                 /* Warn the user via a dialog: */
1024                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_invalid_email"));
1025                                          
1026                 /* Return focus to the email address entry: */
1027                 gtk_widget_grab_focus (priv->entry_user_email);
1028                 gtk_editable_select_region (GTK_EDITABLE (priv->entry_user_email), 0, -1);
1029                 return FALSE;
1030         }
1031
1032         /* make sure the domain name for the incoming server is valid */
1033         const gchar* hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_incomingserver));
1034         if ((!hostname) || (strlen(hostname) == 0)) {
1035                 return FALSE;
1036         }
1037         
1038         if (!modest_text_utils_validate_domain_name (hostname)) {
1039                 /* Warn the user via a dialog: */
1040                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_invalid_servername"));
1041                                          
1042                 /* Return focus to the email address entry: */
1043                 gtk_widget_grab_focus (priv->entry_incomingserver);
1044                 gtk_editable_select_region (GTK_EDITABLE (priv->entry_incomingserver), 0, -1);
1045                 return FALSE;
1046         }
1047
1048         /* make sure the domain name for the outgoing server is valid */
1049         const gchar* hostname2 = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
1050         if ((!hostname2) || (strlen(hostname2) == 0)) {
1051                 return FALSE;
1052         }
1053         
1054         if (!modest_text_utils_validate_domain_name (hostname2)) {
1055                 /* Warn the user via a dialog: */
1056                 modest_platform_information_banner (priv->entry_outgoingserver, NULL, _("mcen_ib_invalid_servername"));
1057
1058                 /* Return focus to the email address entry: */
1059                 gtk_widget_grab_focus (priv->entry_outgoingserver);
1060                 gtk_editable_select_region (GTK_EDITABLE (priv->entry_outgoingserver), 0, -1);
1061                 return FALSE;
1062         }
1063         
1064         /* Find a suitable authentication method when secure authentication is desired */
1065
1066         const gint port_num = gtk_spin_button_get_value_as_int (
1067                         GTK_SPIN_BUTTON (priv->entry_incoming_port));
1068         const gchar* username = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username));
1069
1070         /*
1071         const ModestProtocolType protocol_security_incoming = modest_serversecurity_combo_box_get_active_serversecurity (
1072                 MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security));
1073         */
1074         /* If we use an encrypted protocol then there is no need to encrypt the password */
1075         /* I don't think this is a good assumption. It overrides the user's request. murrayc: 
1076          *  if (!modest_protocol_info_is_secure(protocol_security_incoming)) */
1077         if (TRUE)
1078         {
1079                 if (gtk_toggle_button_get_active (
1080                                 GTK_TOGGLE_BUTTON (priv->checkbox_incoming_auth))) {
1081                         GError *error = NULL;
1082
1083                         GList *list_auth_methods = 
1084                                 modest_utils_get_supported_secure_authentication_methods (priv->incoming_protocol, 
1085                                         hostname, port_num, username, GTK_WINDOW (self), &error);
1086                         if (list_auth_methods) {
1087                                 /* Use the first supported method.
1088                                  * TODO: Should we prioritize them, to prefer a particular one? */
1089                                 GList* method;
1090                                 for (method = list_auth_methods; method != NULL; method = g_list_next(method))
1091                                 {
1092                                         ModestProtocolType proto = (ModestProtocolType)(GPOINTER_TO_INT(method->data));
1093                                         // Allow secure methods, e.g MD5 only
1094                                         if (modest_protocol_registry_protocol_type_is_secure (modest_runtime_get_protocol_registry (), proto))
1095                                         {
1096                                                 priv->protocol_authentication_incoming = proto;
1097                                                 break;
1098                                         }
1099                                 }
1100                                 g_list_free (list_auth_methods);
1101                         }
1102
1103                         if (list_auth_methods == NULL || 
1104                             !modest_protocol_registry_protocol_type_is_secure (modest_runtime_get_protocol_registry (),
1105                                                                                priv->protocol_authentication_incoming)) {
1106                                 if(error == NULL || error->domain != modest_utils_get_supported_secure_authentication_error_quark() ||
1107                                                 error->code != MODEST_UTILS_GET_SUPPORTED_SECURE_AUTHENTICATION_ERROR_CANCELED)
1108                                         modest_platform_information_banner(GTK_WIDGET (self), NULL, 
1109                                                                          _("Could not discover supported secure authentication methods."));
1110
1111                                 if(error != NULL)
1112                                         g_error_free(error);
1113                                         
1114                                 /* This is a nasty hack. jschmid. */
1115                                 /* Don't let the dialog close */
1116                                 /*g_signal_stop_emission_by_name (dialog, "response");*/
1117                                 return FALSE;
1118                         }
1119                 }
1120         }
1121         
1122         return TRUE;
1123 }
1124 /*
1125  */
1126 static void 
1127 on_response (GtkDialog *wizard_dialog,
1128         gint response_id,
1129         gpointer user_data)
1130 {
1131         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (wizard_dialog);
1132         ModestDefaultAccountSettingsDialogPrivate *priv;
1133
1134         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
1135
1136         enable_buttons (self);
1137         
1138         gboolean prevent_response = FALSE;
1139
1140         /* Warn about unsaved changes: */
1141         if (response_id == GTK_RESPONSE_CANCEL && priv->modified) {
1142                 GtkDialog *dialog = GTK_DIALOG (modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
1143                                                                                          _("imum_nc_wizard_confirm_lose_changes")));
1144                 /* TODO: These button names will be ambiguous, and not specified in the UI specification. */
1145                 
1146                 const gint dialog_response = gtk_dialog_run (dialog);
1147                 gtk_widget_destroy (GTK_WIDGET (dialog));
1148                 
1149                 if (dialog_response != GTK_RESPONSE_OK)
1150                         prevent_response = TRUE;
1151         }
1152         /* Check for invalid input: */
1153         else if (response_id != GTK_RESPONSE_CANCEL && !check_data (self)) {
1154                 prevent_response = TRUE;
1155         }
1156                 
1157         if (prevent_response) {
1158                 /* This is a nasty hack. murrayc. */
1159                 /* Don't let the dialog close */
1160                 g_signal_stop_emission_by_name (wizard_dialog, "response");
1161                 return; 
1162         }
1163                 
1164         if (response_id == GTK_RESPONSE_OK) {
1165                 /* Try to save the changes if modified (NB #59251): */
1166                 if (priv->modified)
1167                 {
1168                         const gboolean saved = save_configuration (self);
1169                         if (saved) {
1170                                 /* Do not show the account-saved dialog if we are just saving this 
1171                                  * temporarily, because from the user's point of view it will not 
1172                                  * really be saved (saved + enabled) until later
1173                                  */
1174                                 if (modest_account_settings_get_account_name (priv->settings) != NULL) {
1175                                         ModestServerAccountSettings *store_settings;
1176                                         ModestServerAccountSettings *transport_settings;
1177                                         const gchar *store_account_name;
1178                                         const gchar *transport_account_name;
1179
1180
1181                                         store_settings = modest_account_settings_get_store_settings (priv->settings);
1182                                         transport_settings = modest_account_settings_get_transport_settings (priv->settings);
1183                                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
1184                                         transport_account_name = modest_server_account_settings_get_account_name (transport_settings);
1185                                         
1186                                         if (store_account_name) {
1187                                                 modest_account_mgr_notify_account_update (priv->account_manager, 
1188                                                                                           store_account_name);
1189                                         }
1190                                         if (transport_account_name) {
1191                                                 modest_account_mgr_notify_account_update (priv->account_manager, 
1192                                                                                           transport_account_name);
1193                                         }
1194                                         g_object_unref (store_settings);
1195                                         g_object_unref (transport_settings);
1196
1197                                         modest_platform_information_banner(NULL, NULL, _("mcen_ib_advsetup_settings_saved"));
1198                                 }
1199                         } else {
1200                                 modest_platform_information_banner (NULL, NULL, _("mail_ib_setting_failed"));
1201                         }
1202                 }
1203         }
1204 }
1205
1206 static void 
1207 modest_account_settings_dialog_init (gpointer g, gpointer iface_data)
1208 {
1209         ModestAccountSettingsDialogClass *iface = (ModestAccountSettingsDialogClass *) g;
1210
1211         iface->load_settings = modest_default_account_settings_dialog_load_settings;
1212 }
1213
1214 static void
1215 modest_default_account_settings_dialog_init (ModestDefaultAccountSettingsDialog *self)
1216 {
1217         ModestDefaultAccountSettingsDialogPrivate *priv;
1218
1219         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);
1220
1221         /* Create the notebook to be used by the GtkDialog base class:
1222          * Each page of the notebook will be a page of the wizard: */
1223         priv->notebook = GTK_NOTEBOOK (gtk_notebook_new());
1224         priv->settings = modest_account_settings_new ();
1225
1226         /* Get the account manager object, 
1227          * so we can check for existing accounts,
1228          * and create new accounts: */
1229         priv->account_manager = modest_runtime_get_account_mgr ();
1230         g_assert (priv->account_manager);
1231         g_object_ref (priv->account_manager);
1232         
1233         priv->protocol_authentication_incoming = MODEST_PROTOCOLS_AUTH_PASSWORD;
1234
1235     /* Create the common pages, 
1236      */
1237         priv->page_account_details = create_page_account_details (self);
1238         priv->page_user_details = create_page_user_details (self);
1239         priv->page_incoming = create_page_incoming (self);
1240         priv->page_outgoing = create_page_outgoing (self);
1241         
1242         /* Add the notebook pages: */
1243         gtk_notebook_append_page (priv->notebook, priv->page_account_details, 
1244                 gtk_label_new (_("mcen_ti_account_settings_account")));
1245         gtk_notebook_append_page (priv->notebook, priv->page_user_details, 
1246                 gtk_label_new (_("mcen_ti_account_settings_userinfo")));
1247         gtk_notebook_append_page (priv->notebook, priv->page_incoming,
1248                 gtk_label_new (_("mcen_ti_advsetup_retrieval")));
1249         gtk_notebook_append_page (priv->notebook, priv->page_outgoing,
1250                 gtk_label_new (_("mcen_ti_advsetup_sending")));
1251                 
1252         GtkDialog *dialog = GTK_DIALOG (self);
1253         gtk_container_add (GTK_CONTAINER (dialog->vbox), GTK_WIDGET (priv->notebook));
1254         gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), MODEST_MARGIN_HALF);
1255         gtk_widget_show (GTK_WIDGET (priv->notebook));
1256         
1257     /* Add the buttons: */
1258         gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1259         gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_SAVE, GTK_RESPONSE_OK);
1260     
1261     /* Connect to the dialog's response signal: */
1262     /* We use connect-before 
1263      * so we can stop the signal emission, 
1264      * to stop the default signal handler from closing the dialog.
1265      */
1266     g_signal_connect (G_OBJECT (self), "response",
1267             G_CALLBACK (on_response), self); 
1268             
1269     priv->modified = FALSE;
1270
1271     /* When this window is shown, hibernation should not be possible, 
1272          * because there is no sensible way to save the state: */
1273     modest_window_mgr_prevent_hibernation_while_window_is_shown (
1274         modest_runtime_get_window_mgr (), GTK_WINDOW (self)); 
1275
1276     gtk_window_set_default_size (GTK_WINDOW (self), 600, 400);
1277
1278 /*     hildon_help_dialog_help_enable (GTK_DIALOG(self), "applications_email_accountsettings", */
1279 /*                                  modest_maemo_utils_get_osso_context()); */
1280 }
1281
1282 ModestAccountSettingsDialog*
1283 modest_default_account_settings_dialog_new (void)
1284 {
1285         return g_object_new (MODEST_TYPE_ACCOUNT_SETTINGS_DIALOG, NULL);
1286 }
1287
1288 /** Update the UI with the stored account details, so they can be edited.
1289  * @account_name: Name of the account, which should contain incoming and outgoing server accounts.
1290  */
1291 static void 
1292 modest_default_account_settings_dialog_load_settings (ModestAccountSettingsDialog *dialog, 
1293                                                       ModestAccountSettings *settings)
1294 {
1295         ModestServerAccountSettings *incoming_account;
1296         ModestServerAccountSettings *outgoing_account;
1297         const gchar *account_name;
1298
1299         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS (settings));
1300         ModestDefaultAccountSettingsDialogPrivate *priv;
1301
1302         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
1303
1304         incoming_account = modest_account_settings_get_store_settings (settings);
1305         outgoing_account = modest_account_settings_get_transport_settings (settings);
1306
1307         account_name = modest_account_settings_get_account_name (settings);
1308                 
1309         /* Save the account name so we can refer to it later: */
1310         if (priv->account_name)
1311                 g_free (priv->account_name);
1312         priv->account_name = g_strdup (account_name);
1313
1314         if (priv->settings)
1315                 g_object_unref (priv->settings);
1316         priv->settings = g_object_ref (settings);
1317         
1318         /* Save the account title so we can refer to it if the user changes it: */
1319         if (priv->original_account_title)
1320                 g_free (priv->original_account_title);
1321         priv->original_account_title = g_strdup (modest_account_settings_get_display_name (settings));
1322         
1323         /* Show the account data in the widgets: */
1324         
1325         /* Note that we never show the non-display name in the UI.
1326          * (Though the display name defaults to the non-display name at the start.) */
1327         gtk_entry_set_text( GTK_ENTRY (priv->entry_account_title),
1328                             null_means_empty (modest_account_settings_get_display_name (settings)));
1329         gtk_entry_set_text( GTK_ENTRY (priv->entry_user_name), 
1330                             null_means_empty (modest_account_settings_get_fullname (settings)));
1331         gtk_entry_set_text( GTK_ENTRY (priv->entry_user_email), 
1332                             null_means_empty (modest_account_settings_get_email_address (settings)));
1333         modest_retrieve_combo_box_fill (MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve), 
1334                                         modest_server_account_settings_get_protocol (incoming_account));
1335         modest_retrieve_combo_box_set_active_retrieve_conf (MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve), 
1336                                                             modest_account_settings_get_retrieve_type (settings));
1337         modest_limit_retrieve_combo_box_set_active_limit_retrieve (
1338                 MODEST_LIMIT_RETRIEVE_COMBO_BOX (priv->combo_limit_retrieve), 
1339                 modest_account_settings_get_retrieve_limit (settings));
1340         
1341         
1342         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbox_leave_messages), 
1343                                       modest_account_settings_get_leave_messages_on_server (settings));
1344         
1345         /* Only show the leave-on-server checkbox for POP, 
1346          * as per the UI spec: */
1347         if (modest_server_account_settings_get_protocol (incoming_account) != MODEST_PROTOCOLS_STORE_POP) {
1348                 gtk_widget_hide (priv->caption_leave_messages);
1349         } else {
1350                 gtk_widget_show (priv->caption_leave_messages);
1351         }
1352         
1353         update_incoming_server_security_choices (dialog, modest_server_account_settings_get_protocol (incoming_account));
1354         if (incoming_account) {
1355                 const gchar *username;
1356                 const gchar *password;
1357                 const gchar *hostname;
1358                 /* Remember this for later: */
1359                 priv->incoming_protocol = modest_server_account_settings_get_protocol (incoming_account);;
1360                 
1361                 hostname = modest_server_account_settings_get_hostname (incoming_account);
1362                 username = modest_server_account_settings_get_username (incoming_account);
1363                 password = modest_server_account_settings_get_password (incoming_account);
1364                 gtk_entry_set_text( GTK_ENTRY (priv->entry_user_username),
1365                                     null_means_empty (username));
1366                 gtk_entry_set_text( GTK_ENTRY (priv->entry_user_password), 
1367                                     null_means_empty (password));
1368                         
1369                 gtk_entry_set_text( GTK_ENTRY (priv->entry_incomingserver), 
1370                                     null_means_empty (hostname));
1371                         
1372                 /* The UI spec says:
1373                  * If secure authentication is unchecked, allow sending username and password also as plain text.
1374          * If secure authentication is checked, require one of the secure methods during connection: SSL, TLS, CRAM-MD5 etc. 
1375                  * TODO: Do we need to discover which of these (SSL, TLS, CRAM-MD5) is supported?
1376          */                                                                                                              
1377                 modest_serversecurity_combo_box_set_active_serversecurity (
1378                         MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security), 
1379                         modest_server_account_settings_get_security_protocol (incoming_account));
1380                 
1381                 /* Check if we have
1382                  - a secure protocol
1383                  OR
1384                  - use encrypted passwords
1385                 */
1386                 const ModestProtocolType secure_auth = modest_server_account_settings_get_auth_protocol (incoming_account);
1387                 priv->protocol_authentication_incoming = (secure_auth != MODEST_PROTOCOLS_AUTH_NONE)?
1388                         secure_auth:MODEST_PROTOCOLS_AUTH_PASSWORD;
1389                 if (modest_protocol_registry_protocol_type_is_secure(modest_runtime_get_protocol_registry (),
1390                                                                      secure_auth))
1391                 {
1392                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (priv->checkbox_incoming_auth), 
1393                                                      TRUE);
1394                 }
1395                 else
1396                 {
1397                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (priv->checkbox_incoming_auth), 
1398                                                      FALSE);
1399                 };
1400                                         
1401                 update_incoming_server_title (dialog, priv->incoming_protocol);
1402                 
1403                 const gint port_num = modest_server_account_settings_get_port (incoming_account);
1404                 if (port_num == 0) {
1405                         /* Show the appropriate port number: */
1406                         on_combo_incoming_security_changed (
1407                                 GTK_COMBO_BOX (priv->combo_incoming_security), dialog);
1408                 } else {
1409                         /* Keep the user-entered port-number,
1410                          * or the already-appropriate automatic port number: */
1411                         gtk_spin_button_set_value (
1412                                 GTK_SPIN_BUTTON (priv->entry_incoming_port), (gdouble) port_num);
1413                 }
1414                 g_object_unref (incoming_account);
1415         }
1416         
1417         outgoing_account = modest_account_settings_get_transport_settings (settings);
1418         if (outgoing_account) {
1419                 const gchar *hostname;
1420                 const gchar *username;
1421                 const gchar *password;
1422
1423                 /* Remember this for later: */
1424                 priv->outgoing_protocol = 
1425                         modest_server_account_settings_get_protocol (outgoing_account);
1426
1427                 hostname = modest_server_account_settings_get_hostname (outgoing_account);
1428                 username = modest_server_account_settings_get_username (outgoing_account);
1429                 password = modest_server_account_settings_get_password (outgoing_account);
1430                 gtk_entry_set_text( GTK_ENTRY (priv->entry_outgoingserver), 
1431                                     null_means_empty (hostname));
1432                 
1433                 gtk_entry_set_text( GTK_ENTRY (priv->entry_outgoing_username), 
1434                                     null_means_empty (username));
1435                 gtk_entry_set_text( GTK_ENTRY (priv->entry_outgoing_password), 
1436                                     null_means_empty (password));
1437                 
1438                 /* Get the secure-auth setting: */
1439                 const ModestProtocolType secure_auth = modest_server_account_settings_get_auth_protocol (outgoing_account);
1440                 modest_secureauth_combo_box_set_active_secureauth (
1441                         MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth), secure_auth);
1442                 on_combo_outgoing_auth_changed (GTK_COMBO_BOX (priv->combo_outgoing_auth), dialog);
1443                 
1444                 modest_serversecurity_combo_box_fill (
1445                         MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security), 
1446                         priv->outgoing_protocol);
1447                 
1448                 /* Get the security setting: */
1449                 const ModestProtocolType security = 
1450                         modest_server_account_settings_get_security_protocol (outgoing_account);
1451                 modest_serversecurity_combo_box_set_active_serversecurity (
1452                         MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security), security);
1453                 
1454                 const gint port_num = modest_server_account_settings_get_port (outgoing_account);
1455                 if (port_num == 0) {
1456                         /* Show the appropriate port number: */
1457                         on_combo_outgoing_security_changed (
1458                                 GTK_COMBO_BOX (priv->combo_outgoing_security), dialog);
1459                 }
1460                 else {
1461                         /* Keep the user-entered port-number,
1462                          * or the already-appropriate automatic port number: */
1463                         gtk_spin_button_set_value (
1464                                 GTK_SPIN_BUTTON (priv->entry_outgoing_port), (gdouble) port_num);
1465                 }
1466                 
1467                 const gboolean has_specific = 
1468                         modest_account_settings_get_use_connection_specific_smtp (settings);
1469                 gtk_toggle_button_set_active (
1470                         GTK_TOGGLE_BUTTON (priv->checkbox_outgoing_smtp_specific), 
1471                         has_specific);
1472                 g_object_unref (outgoing_account);
1473         }
1474
1475         /* Set window title according to account: */
1476         /* TODO: Is this the correct way to find a human-readable name for
1477          * the protocol used? */
1478         ModestProtocol *proto = 
1479                 modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), 
1480                                                                priv->incoming_protocol);
1481
1482         const gchar* proto_str = modest_protocol_get_display_name (proto);
1483         gchar *proto_name = g_utf8_strup(proto_str, -1);
1484         const gchar *account_title = modest_account_settings_get_display_name(settings);
1485
1486         gchar *title = g_strdup_printf(_("mcen_ti_account_settings"), proto_name, account_title);
1487         g_free (proto_name);
1488
1489         gtk_window_set_title (GTK_WINDOW (dialog), title);
1490         g_free (title);
1491
1492         /* account_data->is_enabled,  */
1493         /*account_data->is_default,  */
1494
1495         /* Unset the modified flag so we can detect changes later: */
1496         priv->modified = FALSE;
1497 }
1498
1499 /** Show the User Info tab.
1500  */
1501 void 
1502 modest_account_settings_dialog_switch_to_user_info (ModestAccountSettingsDialog *dialog)
1503 {
1504         ModestDefaultAccountSettingsDialogPrivate *priv;
1505
1506         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
1507
1508         const gint page_num = gtk_notebook_page_num (priv->notebook, priv->page_user_details);
1509         if (page_num == -1) {
1510                 g_warning ("%s: notebook page not found.\n", __FUNCTION__);     
1511         }
1512                 
1513         /* Ensure that the widget is visible so that gtk_notebook_set_current_page() works: */
1514         /* TODO: even this hack (recommened by the GTK+ documentation) doesn't seem to work. */
1515         
1516         gtk_widget_show (priv->page_user_details);
1517         gtk_widget_show (GTK_WIDGET (priv->notebook));
1518         gtk_widget_show (GTK_WIDGET (dialog));
1519         gtk_notebook_set_current_page (priv->notebook, page_num);
1520 }
1521
1522 static gboolean
1523 save_configuration (ModestAccountSettingsDialog *dialog)
1524 {
1525         ModestServerAccountSettings *store_settings;
1526         ModestServerAccountSettings *transport_settings;
1527         ModestDefaultAccountSettingsDialogPrivate *priv;
1528
1529         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
1530                 
1531         /* Set the account data from the widgets: */
1532         const gchar* account_name = priv->account_name;
1533         const gchar* user_fullname = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_name));
1534         modest_account_settings_set_fullname (priv->settings, user_fullname);
1535         
1536         const gchar* emailaddress = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_email));
1537         modest_account_settings_set_email_address (priv->settings, emailaddress);
1538                 
1539 /*      /\* Signature: *\/ */
1540 /*      if (priv->signature_dialog) { */
1541 /*              gboolean use_signature = FALSE; */
1542 /*              gchar *signature =  */
1543 /*                      modest_signature_editor_dialog_get_settings (MODEST_SIGNATURE_EDITOR_DIALOG (priv->signature_dialog), */
1544 /*                                                                   &use_signature); */
1545         
1546 /*              modest_account_settings_set_use_signature (priv->settings, use_signature); */
1547 /*              modest_account_settings_set_signature (priv->settings, signature); */
1548 /*      } */
1549         
1550         ModestAccountRetrieveType retrieve_type = modest_retrieve_combo_box_get_active_retrieve_conf (
1551                 MODEST_RETRIEVE_COMBO_BOX (priv->combo_retrieve));
1552         modest_account_settings_set_retrieve_type (priv->settings, retrieve_type);
1553         
1554         gint retrieve_limit = modest_limit_retrieve_combo_box_get_active_limit_retrieve (
1555                 MODEST_LIMIT_RETRIEVE_COMBO_BOX (priv->combo_limit_retrieve));
1556         modest_account_settings_set_retrieve_limit (priv->settings, retrieve_limit);
1557         
1558         const gboolean leave_on_server = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->checkbox_leave_messages));
1559         modest_account_settings_set_leave_messages_on_server (priv->settings, leave_on_server); 
1560
1561         store_settings = modest_account_settings_get_store_settings (priv->settings);
1562                         
1563         const gchar* hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_incomingserver));
1564         modest_server_account_settings_set_hostname (store_settings, hostname);
1565                                 
1566         const gchar* username = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_username));
1567         modest_server_account_settings_set_username (store_settings, username);
1568         
1569         const gchar* password = gtk_entry_get_text (GTK_ENTRY (priv->entry_user_password));
1570         modest_server_account_settings_set_password (store_settings, password);
1571                         
1572         /* port: */
1573         gint port_num = gtk_spin_button_get_value_as_int (
1574                         GTK_SPIN_BUTTON (priv->entry_incoming_port));
1575         modest_server_account_settings_set_port (store_settings, port_num);
1576                         
1577         /* The UI spec says:
1578          * If secure authentication is unchecked, allow sending username and password also as plain text.
1579          * If secure authentication is checked, require one of the secure 
1580          * methods during connection: SSL, TLS, CRAM-MD5 etc. 
1581          */
1582         
1583         const ModestProtocolType protocol_security_incoming = modest_serversecurity_combo_box_get_active_serversecurity (
1584                 MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_incoming_security));
1585         modest_server_account_settings_set_security_protocol (store_settings, 
1586                                                               protocol_security_incoming);      
1587         modest_server_account_settings_set_auth_protocol (store_settings, 
1588                                                           priv->protocol_authentication_incoming);
1589
1590         g_object_unref (store_settings);
1591         
1592         /* Outgoing: */
1593         transport_settings = modest_account_settings_get_transport_settings (priv->settings);
1594         
1595         hostname = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoingserver));
1596         modest_server_account_settings_set_hostname (transport_settings, hostname);
1597                 
1598         username = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoing_username));
1599         modest_server_account_settings_set_username (transport_settings, username);
1600                 
1601         password = gtk_entry_get_text (GTK_ENTRY (priv->entry_outgoing_password));
1602         modest_server_account_settings_set_password (transport_settings, password);
1603         
1604         const ModestProtocolType protocol_security_outgoing = modest_serversecurity_combo_box_get_active_serversecurity (
1605                 MODEST_SERVERSECURITY_COMBO_BOX (priv->combo_outgoing_security));
1606         modest_server_account_settings_set_security_protocol (transport_settings, 
1607                                                               protocol_security_outgoing);
1608         
1609         const ModestProtocolType protocol_authentication_outgoing = modest_secureauth_combo_box_get_active_secureauth (
1610                 MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth));
1611         modest_server_account_settings_set_auth_protocol (transport_settings, protocol_authentication_outgoing);        
1612         
1613         /* port: */
1614         port_num = gtk_spin_button_get_value_as_int (
1615                         GTK_SPIN_BUTTON (priv->entry_outgoing_port));
1616         modest_server_account_settings_set_port (transport_settings, port_num);
1617         g_object_unref (transport_settings);
1618         
1619         
1620         /* Set the changed account title last, to simplify the previous code: */
1621         gchar* account_title = get_entered_account_title (dialog);
1622         if (!account_title)
1623                 return FALSE; /* Should be prevented already anyway. */
1624                 
1625 /*      if (strcmp (account_title, account_name) != 0) { */
1626         modest_account_settings_set_display_name (priv->settings, account_title);
1627 /*      } */
1628         g_free (account_title);
1629         account_title = NULL;
1630         
1631         /* Save connection-specific SMTP server accounts: */
1632         modest_account_settings_set_use_connection_specific_smtp 
1633                 (priv->settings, 
1634                  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox_outgoing_smtp_specific)));
1635
1636         /* this configuration is not persistent, we should not save */
1637         if (account_name != NULL)
1638                 modest_account_mgr_save_account_settings (priv->account_manager, priv->settings);
1639
1640 /*      if (priv->specific_window) { */
1641 /*              return modest_connection_specific_smtp_window_save_server_accounts ( */
1642 /*                      MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (priv->specific_window)); */
1643 /*      } else { */
1644                 return TRUE;
1645 /*      } */
1646
1647 }
1648
1649 static gboolean entry_is_empty (GtkWidget *entry)
1650 {
1651         if (!entry)
1652                 return FALSE;
1653                 
1654         const gchar* text = gtk_entry_get_text (GTK_ENTRY (entry));
1655         if ((!text) || (strlen(text) == 0))
1656                 return TRUE;
1657         else {
1658                 /* Strip it of whitespace at the start and end: */
1659                 gchar *stripped = g_strdup (text);
1660                 stripped = g_strstrip (stripped);
1661                 
1662                 if (!stripped)
1663                         return TRUE;
1664                         
1665                 const gboolean result = (strlen (stripped) == 0);
1666                 
1667                 g_free (stripped);
1668                 return result;
1669         }
1670 }
1671
1672 static void
1673 enable_buttons (ModestAccountSettingsDialog *self)
1674 {
1675         gboolean enable_ok = TRUE;
1676         ModestProtocolType outgoing_auth_protocol;
1677         ModestDefaultAccountSettingsDialogPrivate *priv;
1678
1679         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);;
1680         
1681         /* The account details title is mandatory: */
1682         if (entry_is_empty(priv->entry_account_title))
1683                 enable_ok = FALSE;
1684
1685         /* The user details username is mandatory: */
1686         if (enable_ok && entry_is_empty(priv->entry_user_username))
1687                 enable_ok = FALSE;
1688                 
1689         /* The user details email address is mandatory: */
1690         if (enable_ok && entry_is_empty (priv->entry_user_email))
1691                 enable_ok = FALSE;
1692
1693         /* The custom incoming server is mandatory: */
1694         if (enable_ok && entry_is_empty(priv->entry_incomingserver))
1695                 enable_ok = FALSE;
1696
1697         /* The custom incoming server is mandatory: */
1698         if (enable_ok && entry_is_empty(priv->entry_outgoingserver))
1699                 enable_ok = FALSE;
1700
1701         /* Outgoing username is mandatory if outgoing auth is secure */
1702         if (priv->combo_outgoing_auth) {
1703                 outgoing_auth_protocol = modest_secureauth_combo_box_get_active_secureauth (
1704                         MODEST_SECUREAUTH_COMBO_BOX (priv->combo_outgoing_auth));
1705                 if (enable_ok && 
1706                     outgoing_auth_protocol != MODEST_PROTOCOLS_AUTH_NONE &&
1707                     entry_is_empty (priv->entry_outgoing_username))
1708                         enable_ok = FALSE;
1709         }
1710                         
1711         /* Enable the buttons, 
1712          * identifying them via their associated response codes:
1713          */
1714         GtkDialog *dialog_base = GTK_DIALOG (self);
1715         gtk_dialog_set_response_sensitive (dialog_base,
1716                                            GTK_RESPONSE_OK,
1717                                            enable_ok);
1718 }
1719
1720 void
1721 modest_account_settings_dialog_check_allow_changes (ModestAccountSettingsDialog *self)
1722 {
1723         ModestServerAccountSettings *incoming_settings;
1724         const gchar *server_account_name;
1725         gboolean username_known;
1726         ModestDefaultAccountSettingsDialogPrivate *priv;
1727
1728         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (self);;
1729
1730         if (!G_IS_OBJECT (priv->settings))
1731                 return;
1732
1733         incoming_settings = modest_account_settings_get_store_settings (priv->settings);
1734         server_account_name = modest_server_account_settings_get_account_name (incoming_settings);
1735
1736         username_known = modest_account_mgr_get_server_account_username_has_succeeded (priv->account_manager, 
1737                                                                                        server_account_name);
1738
1739         /* Enable or disable widgets */
1740         gtk_widget_set_sensitive (priv->entry_user_username, !username_known);
1741         gtk_widget_set_sensitive (priv->entry_incomingserver, !username_known);
1742         gtk_widget_set_sensitive (priv->entry_incoming_port, !username_known);
1743         gtk_widget_set_sensitive (priv->combo_incoming_security, !username_known);
1744 }
1745
1746 void
1747 modest_account_settings_dialog_save_password (ModestAccountSettingsDialog *dialog)
1748 {
1749         ModestDefaultAccountSettingsDialogPrivate *priv;
1750
1751         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS_DIALOG (dialog));
1752
1753         priv = MODEST_DEFAULT_ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE (dialog);
1754         priv->modified = TRUE;
1755 }
1756
1757 static void
1758 modest_default_account_settings_dialog_class_init (ModestDefaultAccountSettingsDialogClass *klass)
1759 {
1760         GObjectClass *object_class = G_OBJECT_CLASS (klass);
1761         g_type_class_add_private (klass, sizeof (ModestDefaultAccountSettingsDialogPrivate));
1762
1763         object_class->get_property = modest_account_settings_dialog_get_property;
1764         object_class->set_property = modest_account_settings_dialog_set_property;
1765         object_class->dispose = modest_account_settings_dialog_dispose;
1766         object_class->finalize = modest_account_settings_dialog_finalize;
1767 }