[gnome-initial-setup] Redo validation on the account page



commit 7a19b2a3de11c84a1eab250bf9f0941597755611
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jan 19 21:36:42 2013 -0500

    Redo validation on the account page
    
    Use the same symbolic icon we use for the caps-lock warning
    instead of the red stop sign. And don't wait for focus-out,
    but show the warning after a short timeout.

 .../pages/account/gis-account-page.c               |  133 +++++++---
 .../pages/account/gis-account-page.ui              |  268 +++++++++++---------
 2 files changed, 247 insertions(+), 154 deletions(-)
---
diff --git a/gnome-initial-setup/pages/account/gis-account-page.c b/gnome-initial-setup/pages/account/gis-account-page.c
index e9fc54a..df9f96a 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.c
+++ b/gnome-initial-setup/pages/account/gis-account-page.c
@@ -61,7 +61,9 @@ struct _GisAccountPagePrivate
   gboolean valid_name;
   gboolean valid_username;
   gboolean valid_password;
+  gboolean valid_confirm;
   const gchar *password_reason;
+  guint reason_timeout;
   ActUserAccountType account_type;
 
   gboolean user_data_unsaved;
@@ -117,6 +119,7 @@ clear_account_page (GisAccountPage *page)
   priv->valid_name = FALSE;
   priv->valid_username = FALSE;
   priv->valid_password = FALSE;
+  priv->valid_confirm = FALSE;
 
   /* FIXME: change this for a large deployment scenario; maybe through a GSetting? */
   priv->account_type = ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
@@ -133,7 +136,10 @@ static gboolean
 local_validate (GisAccountPage *page)
 {
   GisAccountPagePrivate *priv = page->priv;
-  return priv->valid_name && priv->valid_username && priv->valid_password;
+  return priv->valid_name &&
+         priv->valid_username &&
+         priv->valid_password &&
+         priv->valid_confirm;
 }
 
 static gboolean
@@ -278,7 +284,42 @@ username_changed (GtkComboBoxText *combo,
   update_account_page_status (page);
 }
 
-#define MIN_PASSWORD_LEN 6
+static gboolean
+reason_timeout_cb (gpointer data)
+{
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (data);
+  GisAccountPagePrivate *priv = page->priv;
+  GtkWidget *password_entry;
+  GtkWidget *confirm_entry;
+  const gchar *password;
+  const gchar *verify;
+
+  password_entry = WID("account-password-entry");
+  confirm_entry = WID("account-confirm-entry");
+  password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+  verify = gtk_entry_get_text (GTK_ENTRY (confirm_entry));
+
+  if (strlen (password) > 0 && !priv->valid_password)
+    set_entry_validation_error (GTK_ENTRY (password_entry), priv->password_reason);
+
+  if (strlen (verify) > 0 && !priv->valid_confirm)
+    set_entry_validation_error (GTK_ENTRY (confirm_entry), _("Passwords do not match"));
+
+  priv->reason_timeout = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+refresh_reason_timeout (GisAccountPage *page)
+{
+  GisAccountPagePrivate *priv = page->priv;
+
+  if (page->priv->reason_timeout != 0)
+    g_source_remove (page->priv->reason_timeout);
+
+  page->priv->reason_timeout = g_timeout_add (600, reason_timeout_cb, page);
+}
 
 static void
 update_password_entries (GisAccountPage *page)
@@ -291,15 +332,18 @@ update_password_entries (GisAccountPage *page)
   GtkWidget *confirm_entry;
   GtkWidget *username_combo;
   GtkWidget *password_strength;
+  GtkWidget *strength_label;
   gdouble strength;
   gint strength_level;
   const gchar *hint;
   const gchar *long_hint = NULL;
+  gchar *strength_hint;
 
   password_entry = WID("account-password-entry");
   confirm_entry = WID("account-confirm-entry");
   username_combo = WID("account-username-combo");
   password_strength = WID("account-password-strength");
+  strength_label = WID("account-password-strength-label");
 
   password = gtk_entry_get_text (GTK_ENTRY (password_entry));
   verify = gtk_entry_get_text (GTK_ENTRY (confirm_entry));
@@ -308,17 +352,35 @@ update_password_entries (GisAccountPage *page)
   strength = pw_strength (password, NULL, username, &hint, &long_hint, &strength_level);
   gtk_level_bar_set_value (GTK_LEVEL_BAR (password_strength), strength_level);
 
+  if (strlen (password) == 0)
+    strength_hint = g_strdup ("");
+  else
+    strength_hint = g_strdup_printf (_("Strength: %s"), hint);
+  gtk_label_set_label (GTK_LABEL (strength_label), strength_hint);
+  g_free (strength_hint);
+
   if (strength == 0.0) {
     priv->valid_password = FALSE;
     priv->password_reason = long_hint ? long_hint : hint;
   }
-  else if (strcmp (password, verify) != 0) {
-    priv->valid_password = FALSE;
-    priv->password_reason = _("Passwords do not match");
-  }
   else {
     priv->valid_password = TRUE;
+    priv->password_reason = NULL;
   }
+
+  priv->valid_confirm = priv->valid_password &&
+                        strcmp (password, verify) == 0;
+
+  if (priv->valid_password) {
+    clear_entry_validation_error (GTK_ENTRY (password_entry));
+    gtk_widget_set_sensitive (confirm_entry, TRUE);
+  } else {
+    gtk_widget_set_sensitive (confirm_entry, FALSE);
+    gtk_entry_set_text (GTK_ENTRY (confirm_entry), "");
+    clear_entry_validation_error (GTK_ENTRY (confirm_entry));
+  }
+
+  refresh_reason_timeout (page);
 }
 
 static void
@@ -327,50 +389,46 @@ password_changed (GtkWidget      *w,
                   GisAccountPage *page)
 {
   GisAccountPagePrivate *priv = page->priv;
+  clear_entry_validation_error (GTK_ENTRY (w));
   update_password_entries (page);
-
   priv->user_data_unsaved = TRUE;
   update_account_page_status (page);
 }
 
-static void
-confirm_changed (GtkWidget      *w,
-                 GParamSpec     *pspec,
-                 GisAccountPage *page)
+static gboolean
+password_entry_focus_out (GtkWidget      *widget,
+                          GdkEventFocus  *event,
+                          GisAccountPage *page)
 {
   GisAccountPagePrivate *priv = page->priv;
-  clear_entry_validation_error (GTK_ENTRY (w));
-  update_password_entries (page);
+  GtkEntry *entry = GTK_ENTRY (widget);
 
-  priv->user_data_unsaved = TRUE;
-  update_account_page_status (page);
+  if (page->priv->reason_timeout != 0)
+    g_source_remove (page->priv->reason_timeout);
+
+  if (!priv->valid_password)
+    set_entry_validation_error (entry, priv->password_reason);
+  else
+    clear_entry_validation_error (entry);
+
+  return FALSE;
 }
 
 static gboolean
-confirm_entry_focus_out (GtkWidget      *entry,
+confirm_entry_focus_out (GtkWidget      *widget,
                          GdkEventFocus  *event,
                          GisAccountPage *page)
 {
   GisAccountPagePrivate *priv = page->priv;
-  const gchar *password;
+  GtkEntry *entry = GTK_ENTRY (widget);
   const gchar *verify;
-  GtkEntry *password_entry;
-  GtkEntry *confirm_entry;
-
-  password_entry = OBJ(GtkEntry*, "account-password-entry");
-  confirm_entry = OBJ(GtkEntry*, "account-confirm-entry");
-  password = gtk_entry_get_text (password_entry);
-  verify = gtk_entry_get_text (confirm_entry);
-
-  if (strlen (password) > 0 && strlen (verify) > 0) {
-    if (!priv->valid_password) {
-      set_entry_validation_error (confirm_entry,
-                                  priv->password_reason);
-    }
-    else {
-      clear_entry_validation_error (confirm_entry);
-    }
-  }
+
+  verify = gtk_entry_get_text (entry);
+
+  if (strlen (verify) > 0 && !priv->valid_confirm)
+    set_entry_validation_error (entry, _("Passwords do not match"));
+  else
+    clear_entry_validation_error (entry);
 
   return FALSE;
 }
@@ -425,7 +483,8 @@ local_create_user (GisAccountPage *page)
   /* this can happen when going back */
   if (!priv->valid_name ||
       !priv->valid_username ||
-      !priv->valid_password) {
+      !priv->valid_password ||
+      !priv->valid_confirm) {
     return;
   }
 
@@ -869,7 +928,9 @@ gis_account_page_constructed (GObject *object)
   g_signal_connect (password_entry, "notify::text",
                     G_CALLBACK (password_changed), page);
   g_signal_connect (confirm_entry, "notify::text",
-                    G_CALLBACK (confirm_changed), page);
+                    G_CALLBACK (password_changed), page);
+  g_signal_connect_after (password_entry, "focus-out-event",
+                          G_CALLBACK (password_entry_focus_out), page);
   g_signal_connect_after (confirm_entry, "focus-out-event",
                           G_CALLBACK (confirm_entry_focus_out), page);
 
diff --git a/gnome-initial-setup/pages/account/gis-account-page.ui b/gnome-initial-setup/pages/account/gis-account-page.ui
index 529cc92..41f256d 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.ui
+++ b/gnome-initial-setup/pages/account/gis-account-page.ui
@@ -1,40 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkListStore" id="account-username-model">
-    <columns>
-      <!-- column-name gchararray -->
-      <column type="gchararray"/>
-    </columns>
-  </object>
-  <object class="GtkListStore" id="enterprise-realms-model">
-    <columns>
-      <!-- column-name gchararray -->
-      <column type="gchararray"/>
-      <!-- column-name gobject -->
-      <column type="GObject"/>
-    </columns>
-  </object>
-  <object class="GtkSizeGroup" id="sizegroup">
-    <widgets>
-      <widget name="sizer1"/>
-      <widget name="sizer2"/>
-      <widget name="sizer3"/>
-      <widget name="sizer4"/>
-      <widget name="account-password-strength"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="sizegroup1">
-    <widgets>
-      <widget name="account-fullname-label"/>
-      <widget name="account-username-label"/>
-      <widget name="account-password-label"/>
-      <widget name="account-confirm-label"/>
-      <widget name="label4"/>
-      <widget name="label8"/>
-      <widget name="label9"/>
-    </widgets>
-  </object>
   <object class="GtkBox" id="account-page">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -44,6 +10,8 @@
       <object class="GtkNotebook" id="account-notebook">
         <property name="visible">True</property>
         <property name="can_focus">True</property>
+        <property name="margin_left">80</property>
+        <property name="margin_right">80</property>
         <property name="show_tabs">False</property>
         <property name="show_border">False</property>
         <child>
@@ -53,34 +21,6 @@
             <property name="row_spacing">6</property>
             <property name="column_spacing">12</property>
             <child>
-              <object class="GtkFrame" id="sizer1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-              </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="sizer2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-              </object>
-              <packing>
-                <property name="left_attach">3</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
               <object class="GtkLabel" id="local-title">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -95,7 +35,7 @@
                 </attributes>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
                 <property name="width">2</property>
                 <property name="height">1</property>
@@ -112,7 +52,7 @@
                 <property name="mnemonic_widget">account-fullname-entry</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">1</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -122,12 +62,11 @@
               <object class="GtkEntry" id="account-fullname-entry">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="halign">start</property>
                 <property name="invisible_char">â</property>
                 <property name="invisible_char_set">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">1</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -144,7 +83,7 @@
                 <property name="mnemonic_widget">account-username-combo</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">2</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -154,7 +93,6 @@
               <object class="GtkComboBoxText" id="account-username-combo">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="halign">start</property>
                 <property name="has_entry">True</property>
                 <property name="entry_text_column">0</property>
                 <property name="id_column">1</property>
@@ -165,7 +103,7 @@
                 </child>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">2</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -176,15 +114,15 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">start</property>
+                <property name="margin_bottom">12</property>
                 <property name="label" translatable="yes">This will be used to name your home folder and can't be changed.</property>
                 <property name="wrap">True</property>
-                <property name="margin_bottom">12</property>
                 <attributes>
                   <attribute name="scale" value="0.8"/>
                 </attributes>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">3</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -201,7 +139,7 @@
                 <property name="mnemonic_widget">account-password-entry</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">4</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -211,29 +149,12 @@
               <object class="GtkEntry" id="account-password-entry">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="halign">start</property>
                 <property name="visibility">False</property>
                 <property name="invisible_char">â</property>
                 <property name="invisible_char_set">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
-                <property name="top_attach">4</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLevelBar" id="account-password-strength">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="halign">start</property>
-                <property name="valign">center</property>
-            <property name="max-value">4</property>
-            <property name="mode">discrete</property>
-              </object>
-              <packing>
-                <property name="left_attach">3</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">4</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -250,7 +171,7 @@
                 <property name="mnemonic_widget">account-confirm-entry</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">5</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -260,13 +181,13 @@
               <object class="GtkEntry" id="account-confirm-entry">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="halign">start</property>
                 <property name="visibility">False</property>
+                <property name="sensitive">False</property>
                 <property name="invisible_char">â</property>
                 <property name="invisible_char_set">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">5</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -284,12 +205,79 @@
                 </attributes>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">6</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkBox" id="box1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="valign">start</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">2</property>
+                <child>
+                  <object class="GtkLabel" id="account-password-strength-label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label"></property>
+                    <attributes>
+                      <attribute name="scale" value="0.8"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLevelBar" id="account-password-strength">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="valign">center</property>
+                    <property name="max-value">4</property>
+                    <property name="mode">discrete</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">2</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
         </child>
         <child type="tab">
@@ -324,20 +312,6 @@
               </packing>
             </child>
             <child>
-              <object class="GtkFrame" id="sizer4">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-              </object>
-              <packing>
-                <property name="left_attach">3</property>
-                <property name="top_attach">0</property>
-                <property name="width">1</property>
-                <property name="height">1</property>
-              </packing>
-            </child>
-            <child>
               <object class="GtkLabel" id="enterprise-title">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -352,7 +326,7 @@
                 </attributes>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">0</property>
                 <property name="width">2</property>
                 <property name="height">1</property>
@@ -369,7 +343,7 @@
                 <property name="mnemonic_widget">enterprise-domain</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">1</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -381,12 +355,12 @@
                 <property name="can_focus">False</property>
                 <property name="halign">end</property>
                 <property name="xalign">1</property>
-                <property name="label" translatable="yes">_Login Name</property>
+                <property name="label" translatable="yes">_Username</property>
                 <property name="use_underline">True</property>
                 <property name="mnemonic_widget">enterprise-login</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">3</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -403,7 +377,7 @@
                 <property name="mnemonic_widget">enterprise-password</property>
               </object>
               <packing>
-                <property name="left_attach">1</property>
+                <property name="left_attach">0</property>
                 <property name="top_attach">4</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -418,7 +392,7 @@
                 <property name="invisible_char_set">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">3</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -435,7 +409,7 @@
                 <property name="invisible_char_set">True</property>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">4</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -456,7 +430,7 @@
                 </child>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">1</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
@@ -466,26 +440,84 @@
               <object class="GtkLabel" id="label10">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="margin_bottom">12</property>
                 <property name="xalign">0</property>
                 <property name="label" translatable="yes">Enterprise domain or realm name</property>
-                <property name="margin_bottom">12</property>
                 <attributes>
                   <attribute name="scale" value="0.8"/>
                 </attributes>
               </object>
               <packing>
-                <property name="left_attach">2</property>
+                <property name="left_attach">1</property>
                 <property name="top_attach">2</property>
                 <property name="width">1</property>
                 <property name="height">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkLabel" id="filler">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+              </object>
+              <packing>
+                <property name="left_attach">2</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
             <property name="position">1</property>
           </packing>
         </child>
       </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
     </child>
   </object>
+  <object class="GtkListStore" id="account-username-model">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="enterprise-realms-model">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+      <!-- column-name gobject -->
+      <column type="GObject"/>
+    </columns>
+  </object>
+  <object class="GtkSizeGroup" id="sizegroup"/>
+  <object class="GtkSizeGroup" id="sizegroup1">
+    <widgets>
+      <widget name="account-fullname-label"/>
+      <widget name="account-username-label"/>
+      <widget name="account-password-label"/>
+      <widget name="account-confirm-label"/>
+      <widget name="label4"/>
+      <widget name="label8"/>
+      <widget name="label9"/>
+    </widgets>
+  </object>
 </interface>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]