2007-04-23 Murray Cumming <murrayc@murrayc.com>
[modest] / src / maemo / modest-account-settings-dialog.c
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  */
5
6
7 #include "modest-account-settings-dialog.h"
8 #include <glib/gi18n.h>
9 #include <gtk/gtknotebook.h>
10 #include <gtk/gtkvbox.h>
11 #include <gtk/gtklabel.h>
12 #include <gtk/gtkcombobox.h>
13 #include <gtk/gtkentry.h>
14 #include <gtk/gtkbutton.h>
15 #include <gtk/gtkcheckbutton.h>
16 #include <gtk/gtkmessagedialog.h>
17 #include <gtk/gtkstock.h>
18 #include <hildon-widgets/hildon-caption.h>
19 #include <hildon-widgets/hildon-number-editor.h>
20 #include "widgets/modest-serversecurity-combo-box.h"
21 #include "widgets/modest-secureauth-combo-box.h"
22 #include "widgets/modest-validating-entry.h"
23 #include "widgets/modest-retrieve-combo-box.h"
24 #include "widgets/modest-limit-retrieve-combo-box.h"
25 #include "modest-text-utils.h"
26 #include "modest-account-mgr.h"
27 #include "modest-account-mgr-helpers.h" /* For modest_account_mgr_get_account_data(). */
28 #include "modest-runtime.h" /* For modest_runtime_get_account_mgr(). */
29 #include "maemo/modest-connection-specific-smtp-window.h"
30 #include <maemo/modest-maemo-ui-constants.h>
31 #include <gconf/gconf-client.h>
32 #include <string.h> /* For strlen(). */
33
34 /* Include config.h so that _() works: */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #define EXAMPLE_EMAIL_ADDRESS "first.last@provider.com"
40
41 G_DEFINE_TYPE (ModestAccountSettingsDialog, modest_account_settings_dialog, GTK_TYPE_DIALOG);
42
43 #define ACCOUNT_SETTINGS_DIALOG_GET_PRIVATE(o) \
44         (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_ACCOUNT_SETTINGS_DIALOG, ModestAccountSettingsDialogPrivate))
45
46 typedef struct _ModestAccountSettingsDialogPrivate ModestAccountSettingsDialogPrivate;
47
48 struct _ModestAccountSettingsDialogPrivate
49 {
50 };
51
52 static void
53 enable_buttons (ModestAccountSettingsDialog *self);
54
55 static gboolean
56 save_configuration (ModestAccountSettingsDialog *dialog);
57
58 static void
59 modest_account_settings_dialog_get_property (GObject *object, guint property_id,
60                                                                                                                         GValue *value, GParamSpec *pspec)
61 {
62         switch (property_id) {
63         default:
64                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
65         }
66 }
67
68 static void
69 modest_account_settings_dialog_set_property (GObject *object, guint property_id,
70                                                                                                                         const GValue *value, GParamSpec *pspec)
71 {
72         switch (property_id) {
73         default:
74                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
75         }
76 }
77
78 static void
79 modest_account_settings_dialog_dispose (GObject *object)
80 {
81         if (G_OBJECT_CLASS (modest_account_settings_dialog_parent_class)->dispose)
82                 G_OBJECT_CLASS (modest_account_settings_dialog_parent_class)->dispose (object);
83 }
84
85 static void
86 modest_account_settings_dialog_finalize (GObject *object)
87 {
88         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (object);
89         
90         if (self->account_name)
91                 g_free (self->account_name);
92                 
93         if (self->original_account_title)
94                 g_free (self->original_account_title);
95                 
96         if (self->account_manager)
97                 g_object_unref (G_OBJECT (self->account_manager));
98                 
99         if (self->specific_window)
100                 gtk_widget_destroy (self->specific_window);
101         
102         G_OBJECT_CLASS (modest_account_settings_dialog_parent_class)->finalize (object);
103 }
104
105 static void
106 show_error (GtkWindow *parent_window, const gchar* text);
107
108 static void
109 show_ok (GtkWindow *parent_window, const gchar* text);
110
111 static void
112 on_combo_incoming_security_changed (GtkComboBox *widget, gpointer user_data);
113
114 static void
115 on_combo_outgoing_security_changed (GtkComboBox *widget, gpointer user_data);
116
117 static void
118 on_modified_combobox_changed (GtkComboBox *widget, gpointer user_data)
119 {
120         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
121         self->modified = TRUE;
122 }
123
124 static void
125 on_modified_entry_changed (GtkEditable *editable, gpointer user_data)
126 {
127         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
128         self->modified = TRUE;
129 }
130
131 static void
132 on_modified_checkbox_toggled (GtkToggleButton *togglebutton, gpointer user_data)
133 {
134         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
135         self->modified = TRUE;
136 }
137
138 /* Set a modified boolean whenever the widget is changed, 
139  * so we can check for it later.
140  */
141 static void
142 connect_for_modified (ModestAccountSettingsDialog *self, GtkWidget *widget)
143 {
144         if (GTK_IS_ENTRY (widget)) {
145           g_signal_connect (G_OBJECT (widget), "changed",
146                 G_CALLBACK (on_modified_entry_changed), self);  
147         } else if (GTK_IS_COMBO_BOX (widget)) {
148                 g_signal_connect (G_OBJECT (widget), "changed",
149                 G_CALLBACK (on_modified_combobox_changed), self);       
150         } else if (GTK_IS_TOGGLE_BUTTON (widget)) {
151                 g_signal_connect (G_OBJECT (widget), "toggled",
152                 G_CALLBACK (on_modified_checkbox_toggled), self);
153         }
154 }
155
156 static void
157 on_caption_entry_changed (GtkEditable *editable, gpointer user_data)
158 {
159         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
160         g_assert(self);
161         enable_buttons(self);
162 }
163
164 static void
165 on_caption_combobox_changed (GtkComboBox *widget, gpointer user_data)
166 {
167         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
168         g_assert(self);
169         enable_buttons(self);
170 }
171
172 /** This is a convenience function to create a caption containing a mandatory widget.
173  * When the widget is edited, the enable_buttons() vfunc will be called.
174  */
175 static GtkWidget* create_caption_new_with_asterix(ModestAccountSettingsDialog *self,
176         GtkSizeGroup *group,
177         const gchar *value,
178         GtkWidget *control,
179         GtkWidget *icon,
180         HildonCaptionStatus flag)
181 {
182   GtkWidget *caption = hildon_caption_new (group, value, control, icon, flag);
183   
184 /* The translated strings seem to already contain the *,
185  * but this code can be used if that is not true in future.
186  */
187 #if 0
188         /* Add a * character to indicate mandatory fields,
189          * as specified in our "Email UI Specification": */
190         if (flag == HILDON_CAPTION_MANDATORY) {
191                 gchar* title = g_strdup_printf("%s*", value);
192                 caption = hildon_caption_new (group, title, control, icon, flag);       
193                 g_free(title);
194         }       
195         else
196                 caption = hildon_caption_new (group, value, control, icon, flag);
197 #endif
198
199         /* Connect to the appropriate changed signal for the widget, 
200          * so we can ask for the prev/next buttons to be enabled/disabled appropriately:
201          */
202         if (GTK_IS_ENTRY (control)) {
203                 g_signal_connect (G_OBJECT (control), "changed",
204                 G_CALLBACK (on_caption_entry_changed), self);
205                 
206         }
207         else if (GTK_IS_COMBO_BOX (control)) {
208                 g_signal_connect (G_OBJECT (control), "changed",
209                 G_CALLBACK (on_caption_combobox_changed), self);
210         }
211          
212         return caption;
213 }
214
215 static GtkWidget*
216 create_page_account_details (ModestAccountSettingsDialog *self)
217 {
218         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
219         GtkWidget *label = gtk_label_new(_("mcen_ia_accountdetails"));
220         gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, MODEST_MARGIN_HALF);
221         gtk_widget_show (label);
222         
223         /* Create a size group to be used by all captions.
224          * Note that HildonCaption does not create a default size group if we do not specify one.
225          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
226         GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
227            
228         /* The description widgets: */  
229         self->entry_account_title = GTK_WIDGET (easysetup_validating_entry_new ());
230         GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_account_title"), 
231                 self->entry_account_title, NULL, HILDON_CAPTION_MANDATORY);
232         gtk_widget_show (self->entry_account_title);
233         connect_for_modified (self, self->entry_account_title);
234         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
235         gtk_widget_show (caption);
236         
237         /* Prevent the use of some characters in the account title, 
238          * as required by our UI specification: */
239         GList *list_prevent = NULL;
240         list_prevent = g_list_append (list_prevent, "\\");
241         list_prevent = g_list_append (list_prevent, "/");
242         list_prevent = g_list_append (list_prevent, ":");
243         list_prevent = g_list_append (list_prevent, "*");
244         list_prevent = g_list_append (list_prevent, "?");
245         list_prevent = g_list_append (list_prevent, "\""); /* The UI spec mentions â€œ, but maybe means ", maybe both. */
246         list_prevent = g_list_append (list_prevent, "“");
247         list_prevent = g_list_append (list_prevent, "<"); 
248         list_prevent = g_list_append (list_prevent, ">"); 
249         list_prevent = g_list_append (list_prevent, "|");
250         list_prevent = g_list_append (list_prevent, "^");       
251         easysetup_validating_entry_set_unallowed_characters (
252                 EASYSETUP_VALIDATING_ENTRY (self->entry_account_title), list_prevent);
253         g_list_free (list_prevent);
254         
255         /* Set max length as in the UI spec:
256          * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
257         gtk_entry_set_max_length (GTK_ENTRY (self->entry_account_title), 64);
258         
259         /* The retrieve combobox: */
260         self->combo_retrieve = GTK_WIDGET (modest_retrieve_combo_box_new ());
261         caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_advsetup_retrievetype"), 
262                 self->combo_retrieve, NULL, HILDON_CAPTION_MANDATORY);
263         gtk_widget_show (self->combo_retrieve);
264         connect_for_modified (self, self->combo_retrieve);
265         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
266         gtk_widget_show (caption);
267         
268         /* The limit-retrieve combobox: */
269         self->combo_limit_retrieve = GTK_WIDGET (modest_limit_retrieve_combo_box_new ());
270         caption = create_caption_new_with_asterix (self, sizegroup, _("mcen_fi_advsetup_limit_retrieve"), 
271                 self->combo_limit_retrieve, NULL, HILDON_CAPTION_MANDATORY);
272         gtk_widget_show (self->combo_limit_retrieve);
273         connect_for_modified (self, self->combo_limit_retrieve);
274         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
275         gtk_widget_show (caption);
276
277         /* The leave-messages widgets: */
278         if(!self->checkbox_leave_messages)
279                 self->checkbox_leave_messages = 
280                         gtk_check_button_new_with_label (_("mcen_fi_advsetup_leave_on_server"));
281         gtk_box_pack_start (GTK_BOX (box), self->checkbox_leave_messages, FALSE, FALSE, MODEST_MARGIN_HALF);
282         gtk_widget_show (self->checkbox_leave_messages);
283         connect_for_modified (self, self->checkbox_leave_messages);
284         
285         gtk_widget_show (GTK_WIDGET (box));
286         
287         return GTK_WIDGET (box);
288 }
289
290 static void
291 on_button_signature (GtkButton *button, gpointer user_data)
292 {
293         
294 }
295
296 static GtkWidget*
297 create_page_user_details (ModestAccountSettingsDialog *self)
298 {
299         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
300         
301         /* Create a size group to be used by all captions.
302          * Note that HildonCaption does not create a default size group if we do not specify one.
303          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
304         GtkSizeGroup* sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
305          
306         /* The name widgets: */
307         self->entry_user_name = GTK_WIDGET (easysetup_validating_entry_new ());
308         /* Set max length as in the UI spec:
309          * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
310         gtk_entry_set_max_length (GTK_ENTRY (self->entry_user_name), 64);
311         GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, 
312                 _("mcen_li_emailsetup_name"), self->entry_user_name, NULL, HILDON_CAPTION_OPTIONAL);
313         gtk_widget_show (self->entry_user_name);
314         connect_for_modified (self, self->entry_user_name);
315         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
316         gtk_widget_show (caption);
317         
318         /* Prevent the use of some characters in the name, 
319          * as required by our UI specification: */
320         GList *list_prevent = NULL;
321         list_prevent = g_list_append (list_prevent, "<");
322         list_prevent = g_list_append (list_prevent, ">");
323         easysetup_validating_entry_set_unallowed_characters (
324                 EASYSETUP_VALIDATING_ENTRY (self->entry_user_name), list_prevent);
325         g_list_free (list_prevent);
326         
327         /* The username widgets: */     
328         self->entry_user_username = GTK_WIDGET (easysetup_validating_entry_new ());
329         caption = create_caption_new_with_asterix (self, sizegroup, _("mail_fi_username"), 
330                 self->entry_user_username, NULL, HILDON_CAPTION_MANDATORY);
331         gtk_widget_show (self->entry_user_username);
332         connect_for_modified (self, self->entry_user_username);
333         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
334         gtk_widget_show (caption);
335         
336         /* Prevent the use of some characters in the username, 
337          * as required by our UI specification: */
338         easysetup_validating_entry_set_unallowed_characters_whitespace (
339                 EASYSETUP_VALIDATING_ENTRY (self->entry_user_username));
340         
341         /* Set max length as in the UI spec:
342          * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
343         gtk_entry_set_max_length (GTK_ENTRY (self->entry_user_username), 64);
344         
345         /* The password widgets: */     
346         self->entry_user_password = gtk_entry_new ();
347         gtk_entry_set_visibility (GTK_ENTRY (self->entry_user_password), FALSE);
348         /* gtk_entry_set_invisible_char (GTK_ENTRY (self->entry_user_password), '*'); */
349         caption = create_caption_new_with_asterix (self, sizegroup, 
350                 _("mail_fi_password"), self->entry_user_password, NULL, HILDON_CAPTION_OPTIONAL);
351         gtk_widget_show (self->entry_user_password);
352         connect_for_modified (self, self->entry_user_password);
353         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
354         gtk_widget_show (caption);
355         
356         /* The email address widgets: */        
357         self->entry_user_email = GTK_WIDGET (easysetup_validating_entry_new ());
358         caption = create_caption_new_with_asterix (self, sizegroup, 
359                 _("mcen_li_emailsetup_email_address"), self->entry_user_email, NULL, HILDON_CAPTION_MANDATORY);
360         gtk_entry_set_text (GTK_ENTRY (self->entry_user_email), EXAMPLE_EMAIL_ADDRESS); /* Default text. */
361         gtk_widget_show (self->entry_user_email);
362         connect_for_modified (self, self->entry_user_email);
363         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
364         gtk_widget_show (caption);
365         
366         /* Set max length as in the UI spec:
367          * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
368         gtk_entry_set_max_length (GTK_ENTRY (self->entry_user_email), 64);
369         
370         
371         /* Signature button: */
372         if (!self->button_signature)
373                 self->button_signature = gtk_button_new_with_label (_("mcen_bd_edit"));
374         caption = hildon_caption_new (sizegroup, _("mcen_fi_email_signature"), 
375                 self->button_signature, NULL, HILDON_CAPTION_OPTIONAL);
376         hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
377         gtk_widget_show (self->button_signature);
378         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
379         gtk_widget_show (caption);
380                 
381         g_signal_connect (G_OBJECT (self->button_signature), "clicked",
382                 G_CALLBACK (on_button_signature), self);
383                 
384         gtk_widget_show (GTK_WIDGET (box));
385         
386         return GTK_WIDGET (box);
387 }
388
389 /** Change the caption title for the incoming server, 
390  * as specified in the UI spec:
391  */
392 static void update_incoming_server_title (ModestAccountSettingsDialog *self, ModestProtocol protocol)
393 {
394         const gchar* type = 
395                 (protocol == MODEST_PROTOCOL_STORE_POP ? 
396                         _("mail_fi_emailtype_pop3") : 
397                         _("mail_fi_emailtype_imap") );
398                         
399                 
400         /* Note that this produces a compiler warning, 
401          * because the compiler does not know that the translated string will have a %s in it.
402          * I do not see a way to avoid the warning while still using these Logical IDs. murrayc. */
403         gchar* incomingserver_title = g_strdup_printf(_("mcen_li_emailsetup_servertype"), type);
404         g_object_set (G_OBJECT (self->caption_incoming), "label", incomingserver_title, NULL);
405         g_free(incomingserver_title);
406 }
407
408 /** Change the caption title for the incoming server, 
409  * as specified in the UI spec:
410  */
411 static void update_incoming_server_security_choices (ModestAccountSettingsDialog *self, ModestProtocol protocol)
412 {
413         /* Fill the combo with appropriately titled choices for POP or IMAP. */
414         /* The choices are the same, but the titles are different, as in the UI spec. */
415         modest_serversecurity_combo_box_fill (
416                 MODEST_SERVERSECURITY_COMBO_BOX (self->combo_incoming_security), protocol);
417 }
418            
419 static GtkWidget* create_page_incoming (ModestAccountSettingsDialog *self)
420 {
421         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
422         
423         /* Create a size group to be used by all captions.
424          * Note that HildonCaption does not create a default size group if we do not specify one.
425          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
426         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
427          
428         /* The incoming server widgets: */
429         if(!self->entry_incomingserver)
430                 self->entry_incomingserver = gtk_entry_new ();
431
432         if (self->caption_incoming)
433           gtk_widget_destroy (self->caption_incoming);
434            
435         /* The caption title will be updated in update_incoming_server_title().
436          * so this default text will never be seen: */
437         /* (Note: Changing the title seems pointless. murrayc) */
438         self->caption_incoming = create_caption_new_with_asterix (self, sizegroup, 
439                 "Incoming Server", self->entry_incomingserver, NULL, HILDON_CAPTION_MANDATORY);
440         gtk_widget_show (self->entry_incomingserver);
441         connect_for_modified (self, self->entry_incomingserver);
442         gtk_box_pack_start (GTK_BOX (box), self->caption_incoming, FALSE, FALSE, MODEST_MARGIN_HALF);
443         gtk_widget_show (self->caption_incoming);
444         
445         /* The secure connection widgets: */
446         /* This will be filled by update_incoming_server_security_choices(). */
447         if (!self->combo_incoming_security)
448                 self->combo_incoming_security = GTK_WIDGET (modest_serversecurity_combo_box_new ());
449         GtkWidget *caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_connection"), 
450                 self->combo_incoming_security, NULL, HILDON_CAPTION_OPTIONAL);
451         gtk_widget_show (self->combo_incoming_security);
452         connect_for_modified (self, self->combo_incoming_security);
453         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
454         gtk_widget_show (caption);
455         
456         /* Show a default port number when the security method changes, as per the UI spec: */
457         g_signal_connect (G_OBJECT (self->combo_incoming_security), "changed", (GCallback)on_combo_incoming_security_changed, self);
458         
459         
460         /* The port widgets: */
461         /* TODO: There are various rules about this in the UI spec. */
462         if (!self->entry_incoming_port)
463                 self->entry_incoming_port = GTK_WIDGET (hildon_number_editor_new (0, 65535));
464         caption = hildon_caption_new (sizegroup, _("mcen_fi_emailsetup_port"), 
465                 self->entry_incoming_port, NULL, HILDON_CAPTION_OPTIONAL);
466         gtk_widget_show (self->entry_incoming_port);
467         connect_for_modified (self, self->entry_incoming_port);
468         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
469         gtk_widget_show (caption);
470         
471         /* The secure authentication widgets: */
472         if(!self->checkbox_incoming_auth)
473                 self->checkbox_incoming_auth = 
474                         gtk_check_button_new_with_label (_("mcen_li_emailsetup_secure_authentication"));
475         gtk_box_pack_start (GTK_BOX (box), self->checkbox_incoming_auth, FALSE, FALSE, MODEST_MARGIN_HALF);
476         gtk_widget_show (self->checkbox_incoming_auth);
477         connect_for_modified (self, self->checkbox_incoming_auth);
478         
479         gtk_widget_show (GTK_WIDGET (box));
480         
481         return GTK_WIDGET (box);
482 }
483
484 static void
485 on_toggle_button_changed (GtkToggleButton *togglebutton, gpointer user_data)
486 {
487         GtkWidget *widget = GTK_WIDGET (user_data);
488         
489         /* Enable the widget only if the toggle button is active: */
490         const gboolean enable = gtk_toggle_button_get_active (togglebutton);
491         gtk_widget_set_sensitive (widget, enable);
492 }
493
494 /* Make the sensitivity of a widget depend on a toggle button.
495  */
496 static void
497 enable_widget_for_togglebutton (GtkWidget *widget, GtkToggleButton* button)
498 {
499         g_signal_connect (G_OBJECT (button), "toggled",
500                 G_CALLBACK (on_toggle_button_changed), widget);
501         
502         /* Set the starting sensitivity: */
503         on_toggle_button_changed (button, widget);
504 }
505
506 static void
507 on_button_outgoing_smtp_servers (GtkButton *button, gpointer user_data)
508 {
509         ModestAccountSettingsDialog * self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
510         
511         /* Create the window if necessary: */
512         if (!(self->specific_window)) {
513                 self->specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
514                 modest_connection_specific_smtp_window_fill_with_connections (
515                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (self->specific_window), self->account_manager, 
516                         self->account_name);
517         }
518
519         /* Show the window: */  
520         gtk_window_set_transient_for (GTK_WINDOW (self->specific_window), GTK_WINDOW (self));
521         gtk_window_set_modal (GTK_WINDOW (self->specific_window), TRUE);
522     gtk_widget_show (self->specific_window);
523 }
524
525 static void
526 on_combo_outgoing_auth_changed (GtkComboBox *widget, gpointer user_data)
527 {
528         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
529         
530         ModestProtocol protocol_security = 
531                 modest_secureauth_combo_box_get_active_secureauth (
532                         MODEST_SECUREAUTH_COMBO_BOX (self->combo_outgoing_auth));
533         const gboolean secureauth_used = protocol_security != MODEST_PROTOCOL_AUTH_NONE;
534         
535         gtk_widget_set_sensitive (self->caption_outgoing_username, secureauth_used);
536         gtk_widget_set_sensitive (self->caption_outgoing_password, secureauth_used);
537 }
538
539 static void
540 on_combo_outgoing_security_changed (GtkComboBox *widget, gpointer user_data)
541 {
542         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
543         
544         const gint port_number = 
545                 modest_serversecurity_combo_box_get_active_serversecurity_port (
546                         MODEST_SERVERSECURITY_COMBO_BOX (self->combo_outgoing_security));
547
548         if(port_number != 0) {
549                 hildon_number_editor_set_value (
550                         HILDON_NUMBER_EDITOR (self->entry_outgoing_port), port_number);
551         }               
552 }
553
554 static void
555 on_combo_incoming_security_changed (GtkComboBox *widget, gpointer user_data)
556 {
557         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (user_data);
558         
559         const gint port_number = 
560                 modest_serversecurity_combo_box_get_active_serversecurity_port (
561                         MODEST_SERVERSECURITY_COMBO_BOX (self->combo_incoming_security));
562
563         if(port_number != 0) {
564                 hildon_number_editor_set_value (
565                         HILDON_NUMBER_EDITOR (self->entry_incoming_port), port_number);
566         }               
567 }
568
569
570 static GtkWidget* create_page_outgoing (ModestAccountSettingsDialog *self)
571 {
572         GtkWidget *box = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
573         
574         /* Create a size group to be used by all captions.
575          * Note that HildonCaption does not create a default size group if we do not specify one.
576          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
577         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
578          
579         /* The outgoing server widgets: */
580         if (!self->entry_outgoingserver)
581                 self->entry_outgoingserver = gtk_entry_new ();
582         GtkWidget *caption = create_caption_new_with_asterix (self, sizegroup, 
583                 _("mcen_li_emailsetup_smtp"), self->entry_outgoingserver, NULL, HILDON_CAPTION_OPTIONAL);
584         gtk_widget_show (self->entry_outgoingserver);
585         connect_for_modified (self, self->entry_outgoingserver);
586         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
587         gtk_widget_show (caption);
588         
589         /* The secure authentication widgets: */
590         if (!self->combo_outgoing_auth)
591                 self->combo_outgoing_auth = GTK_WIDGET (modest_secureauth_combo_box_new ());
592         caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_authentication"), 
593                 self->combo_outgoing_auth, NULL, HILDON_CAPTION_OPTIONAL);
594         gtk_widget_show (self->combo_outgoing_auth);
595         connect_for_modified (self, self->combo_outgoing_auth);
596         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
597         gtk_widget_show (caption);
598         
599         /* Dim the outgoing username and password when no secure authentication is used, as per the UI spec: */
600         g_signal_connect (G_OBJECT (self->combo_outgoing_auth), "changed", (GCallback)on_combo_outgoing_auth_changed, self);
601         
602         /* The username widgets: */     
603         self->entry_outgoing_username = GTK_WIDGET (easysetup_validating_entry_new ());
604         self->caption_outgoing_username = create_caption_new_with_asterix (self, sizegroup, _("mail_fi_username"), 
605                 self->entry_outgoing_username, NULL, HILDON_CAPTION_MANDATORY);
606         gtk_widget_show (self->entry_outgoing_username);
607         connect_for_modified (self, self->entry_outgoing_username);
608         gtk_box_pack_start (GTK_BOX (box), self->caption_outgoing_username, FALSE, FALSE, MODEST_MARGIN_HALF);
609         gtk_widget_show (self->caption_outgoing_username);
610         
611         /* Prevent the use of some characters in the username, 
612          * as required by our UI specification: */
613         easysetup_validating_entry_set_unallowed_characters_whitespace (
614                 EASYSETUP_VALIDATING_ENTRY (self->entry_outgoing_username));
615         
616         /* Set max length as in the UI spec:
617          * TODO: The UI spec seems to want us to show a dialog if we hit the maximum. */
618         gtk_entry_set_max_length (GTK_ENTRY (self->entry_outgoing_username), 64);
619         
620         /* The password widgets: */     
621         self->entry_outgoing_password = gtk_entry_new ();
622         gtk_entry_set_visibility (GTK_ENTRY (self->entry_outgoing_password), FALSE);
623         /* gtk_entry_set_invisible_char (GTK_ENTRY (self->entry_outgoing_password), '*'); */
624         self->caption_outgoing_password = create_caption_new_with_asterix (self, sizegroup, 
625                 _("mail_fi_password"), self->entry_outgoing_password, NULL, HILDON_CAPTION_OPTIONAL);
626         gtk_widget_show (self->entry_outgoing_password);
627         connect_for_modified (self, self->entry_outgoing_password);
628         gtk_box_pack_start (GTK_BOX (box), self->caption_outgoing_password, FALSE, FALSE, MODEST_MARGIN_HALF);
629         gtk_widget_show (self->caption_outgoing_password);
630         
631         /* The secure connection widgets: */
632         /* This will be filled and set with modest_serversecurity_combo_box_fill() 
633          * and modest_serversecurity_combo_box_set_active_serversecurity().
634          */
635         if (!self->combo_outgoing_security)
636                 self->combo_outgoing_security = GTK_WIDGET (modest_serversecurity_combo_box_new ());
637         caption = hildon_caption_new (sizegroup, _("mcen_li_emailsetup_secure_connection"), 
638                 self->combo_outgoing_security, NULL, HILDON_CAPTION_OPTIONAL);
639         gtk_widget_show (self->combo_outgoing_security);
640         connect_for_modified (self, self->combo_outgoing_security);
641         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
642         gtk_widget_show (caption);
643         
644         /* Show a default port number when the security method changes, as per the UI spec: */
645         g_signal_connect (G_OBJECT (self->combo_outgoing_security), "changed", (GCallback)on_combo_outgoing_security_changed, self);
646         
647         /* The port widgets: */
648         if (!self->entry_outgoing_port)
649                 self->entry_outgoing_port = GTK_WIDGET (hildon_number_editor_new (0, 65535));
650         caption = hildon_caption_new (sizegroup, _("mcen_fi_emailsetup_port"), 
651                 self->entry_outgoing_port, NULL, HILDON_CAPTION_OPTIONAL);
652         gtk_widget_show (self->entry_outgoing_port);
653         connect_for_modified (self, self->entry_outgoing_port);
654         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
655         gtk_widget_show (caption);
656         
657         GtkWidget *separator = gtk_hseparator_new ();
658         gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, MODEST_MARGIN_HALF);
659         gtk_widget_show (separator);
660         
661         /* connection-specific checkbox: */
662         if (!self->checkbox_outgoing_smtp_specific) {
663                 self->checkbox_outgoing_smtp_specific = gtk_check_button_new_with_label (_("mcen_fi_advsetup_connection_smtp"));
664                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific), 
665                         FALSE);
666         }
667         gtk_box_pack_start (GTK_BOX (box), self->checkbox_outgoing_smtp_specific, FALSE, FALSE, MODEST_MARGIN_HALF);
668         gtk_widget_show (self->checkbox_outgoing_smtp_specific);
669         connect_for_modified (self, self->checkbox_outgoing_smtp_specific);
670         
671         /* Connection-specific SMTP-Severs Edit button: */
672         if (!self->button_outgoing_smtp_servers)
673                 self->button_outgoing_smtp_servers = gtk_button_new_with_label (_("mcen_bd_edit"));
674         caption = hildon_caption_new (sizegroup, _("mcen_fi_advsetup_optional_smtp"), 
675                 self->button_outgoing_smtp_servers, NULL, HILDON_CAPTION_OPTIONAL);
676         hildon_caption_set_child_expand (HILDON_CAPTION (caption), FALSE);
677         gtk_widget_show (self->button_outgoing_smtp_servers);
678         gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
679         gtk_widget_show (caption);
680         
681         /* Only enable the button when the checkbox is checked: */
682         enable_widget_for_togglebutton (self->button_outgoing_smtp_servers, 
683                 GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific));
684                 
685         g_signal_connect (G_OBJECT (self->button_outgoing_smtp_servers), "clicked",
686                 G_CALLBACK (on_button_outgoing_smtp_servers), self);
687         
688         
689         gtk_widget_show (GTK_WIDGET (box));
690         
691         return GTK_WIDGET (box);
692 }
693
694 static gboolean
695 check_data (ModestAccountSettingsDialog *self)
696 {
697         /* Check that the title is not already in use: */
698         const gchar* account_title = gtk_entry_get_text (GTK_ENTRY (self->entry_account_title));
699         if ((!account_title) || (strlen(account_title) == 0))
700                 return FALSE; /* Should be prevented already anyway. */
701                 
702         if (strcmp(account_title, self->original_account_title) != 0) {
703                 /* Check the changed title: */
704                 const gboolean name_in_use  = modest_account_mgr_account_with_display_name_exists (self->account_manager,
705                         account_title);
706         
707                 if (name_in_use) {
708                         /* Warn the user via a dialog: */
709                         show_error (GTK_WINDOW (self), _("mail_ib_account_name_already_existing"));
710                 
711                         return FALSE;
712                 }
713         }
714
715         /* Check that the email address is valud: */
716         const gchar* email_address = gtk_entry_get_text (GTK_ENTRY (self->entry_user_email));
717         if ((!email_address) || (strlen(email_address) == 0))
718                 return FALSE;
719                         
720         if (!modest_text_utils_validate_email_address (email_address)) {
721                 /* Warn the user via a dialog: */
722                 show_error (GTK_WINDOW (self), _("mcen_ib_invalid_email"));
723                                          
724         /* Return focus to the email address entry: */
725         gtk_widget_grab_focus (self->entry_user_email);
726         
727                 return FALSE;
728         }
729         
730         /* TODO: The UI Spec wants us to check that the servernames are valid, 
731          * but does not specify how.
732          */
733          
734         return TRUE;
735 }
736 /*
737  */
738 static void 
739 on_response (GtkDialog *wizard_dialog,
740         gint response_id,
741         gpointer user_data)
742 {
743         ModestAccountSettingsDialog *self = MODEST_ACCOUNT_SETTINGS_DIALOG (wizard_dialog);
744         enable_buttons (self);
745         
746         gboolean prevent_response = FALSE;
747         
748         /* Warn about unsaved changes: */
749         if (response_id == GTK_RESPONSE_CANCEL && self->modified) {
750                 GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (GTK_WINDOW (self),
751                 (GtkDialogFlags)0,
752                  GTK_MESSAGE_INFO,
753                  GTK_BUTTONS_OK_CANCEL, /* TODO: These button names are ambiguous, and not specified in the UI specification. */
754                  _("imum_nc_wizard_confirm_lose_changes") ));
755                  
756                  const gint dialog_response = gtk_dialog_run (dialog);
757                  gtk_widget_destroy (GTK_WIDGET (dialog));
758                  
759                 if (dialog_response != GTK_RESPONSE_OK)
760                         prevent_response = TRUE;
761         }
762         /* Check for invalid input: */
763         else if (!check_data (self)) {
764                 prevent_response = TRUE;
765         }
766                 
767         if (prevent_response) {
768                 /* This is a nasty hack. murrayc. */
769                 /* Don't let the dialog close */
770         g_signal_stop_emission_by_name (wizard_dialog, "response");
771                 return; 
772         }
773                 
774                 
775         if (response_id == GTK_RESPONSE_OK) {
776                 /* Try to save the changes: */  
777                 const gboolean saved = save_configuration (self);
778                 if (saved)
779                         show_ok (GTK_WINDOW (self), _("mcen_ib_advsetup_settings_saved"));
780                 else
781                         show_error (GTK_WINDOW (self), _("mail_ib_setting_failed"));
782         }
783 }
784
785 static void
786 modest_account_settings_dialog_init (ModestAccountSettingsDialog *self)
787 {
788         /* Create the notebook to be used by the GtkDialog base class:
789          * Each page of the notebook will be a page of the wizard: */
790         GtkNotebook *notebook = GTK_NOTEBOOK (gtk_notebook_new());
791
792     
793     gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_emailsetup"));
794         
795         /* Get the account manager object, 
796          * so we can check for existing accounts,
797          * and create new accounts: */
798         self->account_manager = modest_runtime_get_account_mgr ();
799         g_assert (self->account_manager);
800         g_object_ref (self->account_manager);
801         
802     /* Create the common pages, 
803      */
804         self->page_account_details = create_page_account_details (self);
805         self->page_user_details = create_page_user_details (self);
806         self->page_incoming = create_page_incoming (self);
807         self->page_outgoing = create_page_outgoing (self);
808         
809         /* Add the notebook pages: */
810         gtk_notebook_append_page (notebook, self->page_account_details, 
811                 gtk_label_new (_("mcen_ti_account_settings_account")));
812         gtk_notebook_append_page (notebook, self->page_user_details, 
813                 gtk_label_new (_("mcen_ti_account_settings_userinfo")));
814         gtk_notebook_append_page (notebook, self->page_incoming,
815                 gtk_label_new (_("mcen_ti_advsetup_retrieval")));
816         gtk_notebook_append_page (notebook, self->page_outgoing,
817                 gtk_label_new (_("mcen_ti_advsetup_sending")));
818                 
819         GtkDialog *dialog = GTK_DIALOG (self);
820         gtk_container_add (GTK_CONTAINER (dialog->vbox), GTK_WIDGET (notebook));
821         gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), MODEST_MARGIN_HALF);
822         gtk_widget_show (GTK_WIDGET (notebook));
823         
824     /* Add the buttons: */
825     gtk_dialog_add_button (GTK_DIALOG(self), GTK_STOCK_OK, GTK_RESPONSE_OK);
826     gtk_dialog_add_button (GTK_DIALOG(self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
827     
828     /* Connect to the dialog's response signal: */
829     /* We use connect-before 
830      * so we can stop the signal emission, 
831      * to stop the default signal handler from closing the dialog.
832      */
833     g_signal_connect (G_OBJECT (self), "response",
834             G_CALLBACK (on_response), self); 
835             
836     self->modified = FALSE;      
837 }
838
839 ModestAccountSettingsDialog*
840 modest_account_settings_dialog_new (void)
841 {
842         return g_object_new (MODEST_TYPE_ACCOUNT_SETTINGS_DIALOG, NULL);
843 }
844
845 /** Update the UI with the stored account details, so they can be edited.
846  * @account_name: Name of the account, which should contain incoming and outgoing server accounts.
847  */
848 void modest_account_settings_dialog_set_account_name (ModestAccountSettingsDialog *dialog, const gchar* account_name)
849 {
850         if (!account_name)
851                 return;
852                 
853         /* Save the account name so we can refer to it later: */
854         if (dialog->account_name)
855                 g_free (dialog->account_name);
856         dialog->account_name = g_strdup (account_name);
857         
858                 
859         /* Get the account data for this account name: */
860         ModestAccountData *account_data = modest_account_mgr_get_account_data (dialog->account_manager, 
861                 account_name);
862         if (!account_data) {
863                 g_printerr ("modest: failed to get account data for %s\n", account_name);
864                 return;
865         }
866         
867         /* Save the account title so we can refer to it if the user changes it: */
868         if (dialog->original_account_title)
869                 g_free (dialog->original_account_title);
870         dialog->original_account_title = g_strdup (account_data->display_name);
871         
872
873         if (!(account_data->store_account)) {
874                 g_printerr ("modest: account has no stores: %s\n", account_name);
875                 return;
876         }
877                 
878         /* Show the account data in the widgets: */
879         
880         /* Note that we never show the non-display name in the UI.
881          * (Though the display name defaults to the non-display name at the start.) */
882         gtk_entry_set_text( GTK_ENTRY (dialog->entry_account_title),
883                 account_data->display_name ? account_data->display_name : "");
884                 
885         gtk_entry_set_text( GTK_ENTRY (dialog->entry_user_name), 
886                 account_data->fullname ? account_data->fullname : "");
887         gtk_entry_set_text( GTK_ENTRY (dialog->entry_user_email), 
888                 account_data->email ? account_data->email : "");
889                 
890         ModestServerAccountData *incoming_account = account_data->store_account;
891                 
892         if (incoming_account)
893                 modest_retrieve_combo_box_fill (MODEST_RETRIEVE_COMBO_BOX (dialog->combo_retrieve), incoming_account->proto);
894         gchar *retrieve = modest_account_mgr_get_string (dialog->account_manager, account_name,
895                 MODEST_ACCOUNT_RETRIEVE, FALSE /* not server account */);
896         if (!retrieve) {
897                 /* Default to something, though no default is specified in the UI spec: */
898                 retrieve = g_strdup (MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY);
899         }
900         modest_retrieve_combo_box_set_active_retrieve_conf (MODEST_RETRIEVE_COMBO_BOX (dialog->combo_retrieve), retrieve);
901         g_free (retrieve);
902         
903         const gint limit_retrieve = modest_account_mgr_get_int (dialog->account_manager, account_name,
904                 MODEST_ACCOUNT_LIMIT_RETRIEVE, FALSE /* not server account */);
905         modest_limit_retrieve_combo_box_set_active_limit_retrieve (MODEST_LIMIT_RETRIEVE_COMBO_BOX (dialog->combo_limit_retrieve), limit_retrieve);
906         
907         
908         const gboolean leave_on_server = modest_account_mgr_get_bool (dialog->account_manager, account_name,
909                 MODEST_ACCOUNT_LEAVE_ON_SERVER, FALSE /* not server account */);
910         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbox_leave_messages), leave_on_server);    
911         
912         /* Only show the leave-on-server checkbox for POP, 
913          * as per the UI spec: */
914         if (incoming_account->proto != MODEST_PROTOCOL_STORE_POP) {
915                 gtk_widget_hide (dialog->checkbox_leave_messages);
916         } else {
917                 gtk_widget_show (dialog->checkbox_leave_messages);
918         }
919                 
920         if (incoming_account) {
921                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_user_username),
922                         incoming_account->username ? incoming_account->username : "");
923                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_user_password), 
924                         incoming_account->password ? incoming_account->password : "");
925                         
926                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_incomingserver), 
927                         incoming_account->hostname ? incoming_account->hostname : "");
928                         
929                 const ModestProtocol secure_auth = modest_server_account_get_secure_auth(
930                         dialog->account_manager, incoming_account->account_name);
931                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (dialog->checkbox_incoming_auth), 
932                         secure_auth == MODEST_PROTOCOL_AUTH_PASSWORD);
933                         
934                 update_incoming_server_title (dialog, incoming_account->proto);
935                 update_incoming_server_security_choices (dialog, incoming_account->proto);
936                 
937                 const ModestProtocol security = modest_server_account_get_security (
938                         dialog->account_manager, incoming_account->account_name);
939                 modest_serversecurity_combo_box_set_active_serversecurity (
940                         MODEST_SERVERSECURITY_COMBO_BOX (dialog->combo_incoming_security), security);
941                 
942                 const gint port_num = modest_account_mgr_get_int (dialog->account_manager, incoming_account->account_name,
943                         MODEST_ACCOUNT_PORT, TRUE /* server account */);
944                 hildon_number_editor_set_value (
945                         HILDON_NUMBER_EDITOR (dialog->entry_incoming_port), port_num);
946         
947         }
948         
949         ModestServerAccountData *outgoing_account = account_data->transport_account;
950         if (outgoing_account) {
951                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_outgoingserver), 
952                         outgoing_account->hostname ? outgoing_account->hostname : "");
953                 
954                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_outgoing_username), 
955                         outgoing_account->username ? outgoing_account->username : "");
956                 gtk_entry_set_text( GTK_ENTRY (dialog->entry_outgoing_password), 
957                         outgoing_account->password ? outgoing_account->password : "");
958                 
959                 /* Get the secure-auth setting: */
960                 const ModestProtocol secure_auth = modest_server_account_get_secure_auth(
961                         dialog->account_manager, outgoing_account->account_name);
962                 modest_secureauth_combo_box_set_active_secureauth (
963                         MODEST_SECUREAUTH_COMBO_BOX (dialog->combo_outgoing_auth), secure_auth);
964                 on_combo_outgoing_auth_changed (GTK_COMBO_BOX (dialog->combo_outgoing_auth), dialog);
965                 
966                 modest_serversecurity_combo_box_fill (
967                         MODEST_SERVERSECURITY_COMBO_BOX (dialog->combo_outgoing_security), outgoing_account->proto);
968                 
969                 /* Get the security setting: */
970                 const ModestProtocol security = modest_server_account_get_security (
971                         dialog->account_manager, outgoing_account->account_name);
972                 modest_serversecurity_combo_box_set_active_serversecurity (
973                         MODEST_SERVERSECURITY_COMBO_BOX (dialog->combo_outgoing_security), security);
974                 
975                 const gint port_num = modest_account_mgr_get_int (dialog->account_manager, outgoing_account->account_name,
976                         MODEST_ACCOUNT_PORT, TRUE /* server account */);
977                 hildon_number_editor_set_value (
978                         HILDON_NUMBER_EDITOR (dialog->entry_outgoing_port), port_num);
979         }
980         
981         /* account_data->is_enabled,  */
982         /*account_data->is_default,  */
983
984         /* account_data->store_account->proto */
985
986         modest_account_mgr_free_account_data (dialog->account_manager, account_data);
987         
988         /* Unset the modified flag so we can detect changes later: */
989         dialog->modified = FALSE;
990 }
991
992 static gboolean
993 save_configuration (ModestAccountSettingsDialog *dialog)
994 {
995         g_assert (dialog->account_name);
996         
997         const gchar* account_name = dialog->account_name;
998                 
999         /* Set the account data from the widgets: */
1000         const gchar* user_name = gtk_entry_get_text (GTK_ENTRY (dialog->entry_user_name));
1001         gboolean test = modest_account_mgr_set_string (dialog->account_manager, account_name,
1002                 MODEST_ACCOUNT_FULLNAME, user_name, FALSE /* not server account */);
1003         if (!test)
1004                 return FALSE;
1005                 
1006         const gchar* emailaddress = gtk_entry_get_text (GTK_ENTRY (dialog->entry_user_email));
1007         test = modest_account_mgr_set_string (dialog->account_manager, account_name,
1008                 MODEST_ACCOUNT_EMAIL, emailaddress, FALSE /* not server account */);
1009         if (!test)
1010                 return FALSE;
1011         
1012         gchar *retrieve = modest_retrieve_combo_box_get_active_retrieve_conf (
1013                 MODEST_RETRIEVE_COMBO_BOX (dialog->combo_retrieve));
1014         modest_account_mgr_set_string (dialog->account_manager, account_name,
1015                 MODEST_ACCOUNT_RETRIEVE, retrieve, FALSE /* not server account */);
1016         g_free (retrieve);
1017         
1018         const gint limit_retrieve = modest_limit_retrieve_combo_box_get_active_limit_retrieve (
1019                 MODEST_LIMIT_RETRIEVE_COMBO_BOX (dialog->combo_limit_retrieve));
1020         modest_account_mgr_set_int (dialog->account_manager, account_name,
1021                 MODEST_ACCOUNT_LIMIT_RETRIEVE, limit_retrieve, FALSE /* not server account */);
1022         
1023         const gboolean leave_on_server = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbox_leave_messages));
1024         test = modest_account_mgr_set_bool (dialog->account_manager, account_name,
1025                 MODEST_ACCOUNT_LEAVE_ON_SERVER, leave_on_server, FALSE /* not server account */);
1026         if (!test)
1027                 return FALSE;
1028                         
1029         /* Incoming: */
1030         gchar* incoming_account_name = modest_account_mgr_get_string (dialog->account_manager, account_name,
1031                 MODEST_ACCOUNT_STORE_ACCOUNT, FALSE /* not server account */);
1032         g_assert (incoming_account_name);
1033         
1034         const gchar* hostname = gtk_entry_get_text (GTK_ENTRY (dialog->entry_incomingserver));
1035         test = modest_account_mgr_set_string (dialog->account_manager, incoming_account_name,
1036                 MODEST_ACCOUNT_HOSTNAME, hostname, TRUE /* server account */);
1037         if (!test)
1038                 return FALSE;
1039                                 
1040         const gchar* username = gtk_entry_get_text (GTK_ENTRY (dialog->entry_user_username));
1041         test = modest_account_mgr_set_string (dialog->account_manager, incoming_account_name,
1042                 MODEST_ACCOUNT_USERNAME, username, TRUE /* server account */);
1043         if (!test)
1044                 return FALSE;
1045                                 
1046         const gchar* password = gtk_entry_get_text (GTK_ENTRY (dialog->entry_user_password));
1047         test = modest_account_mgr_set_string (dialog->account_manager, incoming_account_name,
1048                 MODEST_ACCOUNT_PASSWORD, password, TRUE /*  server account */);
1049         if (!test)
1050                 return FALSE;
1051                         
1052         const ModestProtocol protocol_authentication_incoming = gtk_toggle_button_get_active 
1053                 (GTK_TOGGLE_BUTTON (dialog->checkbox_incoming_auth)) 
1054                         ? MODEST_PROTOCOL_AUTH_PASSWORD
1055                         : MODEST_PROTOCOL_AUTH_NONE;
1056         modest_server_account_set_secure_auth (dialog->account_manager, incoming_account_name, protocol_authentication_incoming);
1057                         
1058         const ModestProtocol protocol_security_incoming = modest_serversecurity_combo_box_get_active_serversecurity (
1059                 MODEST_SERVERSECURITY_COMBO_BOX (dialog->combo_incoming_security));
1060         modest_server_account_set_security (dialog->account_manager, incoming_account_name, protocol_security_incoming);
1061         
1062         /* port: */
1063         gint port_num = hildon_number_editor_get_value (
1064                         HILDON_NUMBER_EDITOR (dialog->entry_incoming_port));
1065         modest_account_mgr_set_int (dialog->account_manager, incoming_account_name,
1066                         MODEST_ACCOUNT_PORT, port_num, TRUE /* server account */);
1067                 
1068         g_free (incoming_account_name);
1069         
1070         /* Outgoing: */
1071         gchar* outgoing_account_name = modest_account_mgr_get_string (dialog->account_manager, account_name,
1072                 MODEST_ACCOUNT_TRANSPORT_ACCOUNT, FALSE /* not server account */);
1073         g_assert (outgoing_account_name);
1074         
1075         hostname = gtk_entry_get_text (GTK_ENTRY (dialog->entry_outgoingserver));
1076         test = modest_account_mgr_set_string (dialog->account_manager, outgoing_account_name,
1077                 MODEST_ACCOUNT_HOSTNAME, hostname, TRUE /* server account */);
1078         if (!test)
1079                 return FALSE;
1080                 
1081         username = gtk_entry_get_text (GTK_ENTRY (dialog->entry_outgoing_username));
1082         test = modest_account_mgr_set_string (dialog->account_manager, outgoing_account_name,
1083                 MODEST_ACCOUNT_USERNAME, username, TRUE /* server account */);
1084         if (!test)
1085                 return FALSE;
1086                 
1087         password = gtk_entry_get_text (GTK_ENTRY (dialog->entry_outgoing_password));
1088         test = modest_account_mgr_set_string (dialog->account_manager, outgoing_account_name,
1089                 MODEST_ACCOUNT_PASSWORD, password, TRUE /*  server account */);
1090         if (!test)
1091                 return FALSE;
1092         
1093         const ModestProtocol protocol_security_outgoing = modest_serversecurity_combo_box_get_active_serversecurity (
1094                 MODEST_SERVERSECURITY_COMBO_BOX (dialog->combo_outgoing_security));
1095         modest_server_account_set_security (dialog->account_manager, outgoing_account_name, protocol_security_outgoing);
1096         
1097         const ModestProtocol protocol_authentication_outgoing = modest_secureauth_combo_box_get_active_secureauth (
1098                 MODEST_SECUREAUTH_COMBO_BOX (dialog->combo_outgoing_auth));
1099         modest_server_account_set_secure_auth (dialog->account_manager, outgoing_account_name, protocol_authentication_outgoing);       
1100                 
1101         /* port: */
1102         port_num = hildon_number_editor_get_value (
1103                         HILDON_NUMBER_EDITOR (dialog->entry_outgoing_port));
1104         modest_account_mgr_set_int (dialog->account_manager, outgoing_account_name,
1105                         MODEST_ACCOUNT_PORT, port_num, TRUE /* server account */);
1106                         
1107         g_free (outgoing_account_name);
1108         
1109         
1110         /* Set the changed account title last, to simplify the previous code: */
1111         const gchar* account_title = gtk_entry_get_text (GTK_ENTRY (dialog->entry_account_title));
1112         if ((!account_title) || (strlen(account_title) == 0))
1113                 return FALSE; /* Should be prevented already anyway. */
1114                 
1115         if (strcmp(account_title, account_name) != 0) {
1116                 /* Change the title: */
1117                 gboolean test = modest_account_mgr_set_string (dialog->account_manager, account_name,
1118                 MODEST_ACCOUNT_DISPLAY_NAME, account_title, FALSE /* not server account */);
1119                 if (!test)
1120                         return FALSE;
1121         }
1122         
1123         /* Save connection-specific SMTP server accounts: */
1124         if (dialog->specific_window)
1125                 return modest_connection_specific_smtp_window_save_server_accounts (
1126                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (dialog->specific_window), account_name);
1127         else
1128                 return TRUE;
1129 }
1130
1131 static gboolean entry_is_empty (GtkWidget *entry)
1132 {
1133         if (!entry)
1134                 return FALSE;
1135                 
1136         const gchar* text = gtk_entry_get_text (GTK_ENTRY (entry));
1137         if ((!text) || (strlen(text) == 0))
1138                 return TRUE;
1139         else
1140                 return FALSE;
1141 }
1142
1143 static void
1144 enable_buttons (ModestAccountSettingsDialog *self)
1145 {
1146         gboolean enable_ok = TRUE;
1147         
1148         /* The account details title is mandatory: */
1149         if (entry_is_empty(self->entry_account_title))
1150                         enable_ok = FALSE;
1151
1152         /* The user details username is mandatory: */
1153         if (entry_is_empty(self->entry_user_username))
1154                 enable_ok = FALSE;
1155                 
1156         /* The user details email address is mandatory: */
1157         if (enable_ok && entry_is_empty (self->entry_user_email))
1158                 enable_ok = FALSE;
1159
1160         /* The custom incoming server is mandatory: */
1161         if (entry_is_empty(self->entry_incomingserver))
1162                 enable_ok = FALSE;
1163                         
1164         /* Enable the buttons, 
1165          * identifying them via their associated response codes:
1166          */
1167         GtkDialog *dialog_base = GTK_DIALOG (self);
1168     gtk_dialog_set_response_sensitive (dialog_base,
1169                                        GTK_RESPONSE_OK,
1170                                        enable_ok);
1171 }
1172
1173 static void
1174 modest_account_settings_dialog_class_init (ModestAccountSettingsDialogClass *klass)
1175 {
1176         GObjectClass *object_class = G_OBJECT_CLASS (klass);
1177         g_type_class_add_private (klass, sizeof (ModestAccountSettingsDialogPrivate));
1178
1179
1180         object_class->get_property = modest_account_settings_dialog_get_property;
1181         object_class->set_property = modest_account_settings_dialog_set_property;
1182         object_class->dispose = modest_account_settings_dialog_dispose;
1183         object_class->finalize = modest_account_settings_dialog_finalize;
1184 }
1185  
1186 static void
1187 show_error (GtkWindow *parent_window, const gchar* text)
1188 {
1189         GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
1190                 (GtkDialogFlags)0,
1191                  GTK_MESSAGE_ERROR,
1192                  GTK_BUTTONS_OK,
1193                  text ));
1194                  
1195                  gtk_dialog_run (dialog);
1196                  gtk_widget_destroy (GTK_WIDGET (dialog));
1197 }
1198
1199 static void
1200 show_ok (GtkWindow *parent_window, const gchar* text)
1201 {
1202         GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
1203                 (GtkDialogFlags)0,
1204                  GTK_MESSAGE_INFO,
1205                  GTK_BUTTONS_OK,
1206                  text ));
1207                  
1208                  gtk_dialog_run (dialog);
1209                  gtk_widget_destroy (GTK_WIDGET (dialog));
1210 }
1211
1212
1213