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