The check for whether the password field and the password confirmation field match is run when either field is changed, since changes to either field will cause the state of the match to change. This was working correctly when a change to either field broke the match, but was not always working when a change fixed the match. The check object for the field not changed remained in a failure state, making it impossible to exit the spoke even though the password matched. This fixes that by manually running the check on the field not changed. --- pyanaconda/ui/gui/__init__.py | 11 +++++++++-- pyanaconda/ui/gui/spokes/user.py | 33 ++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index 7f18c4b..f971794 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -98,9 +98,16 @@ class GUICheck(object): self._handler_id = None self._check_status = None
- def update_check_status(self, editable=None, data=None): + def update_check_status(self, editable=None, check_data=None): """Run an input validation check.""" - new_check_status = self._run_check(self._editable, self._check_data) + + # Allow check parameters to be overriden in parameters + if editable is None: + editable = self._editable + if check_data is None: + check_data = self._check_data + + new_check_status = self._run_check(editable, check_data) check_status_changed = (self._check_status != new_check_status) self._check_status = new_check_status
diff --git a/pyanaconda/ui/gui/spokes/user.py b/pyanaconda/ui/gui/spokes/user.py index 1ee9399..dd2d217 100644 --- a/pyanaconda/ui/gui/spokes/user.py +++ b/pyanaconda/ui/gui/spokes/user.py @@ -279,9 +279,13 @@ class UserSpoke(FirstbootSpokeMixIn, NormalSpoke): self.add_check(self.pw, self._checkPasswordEmpty, None)
# The password confirmation needs to be checked whenever either of the password - # fields change - self.add_check(self.confirm, self._checkPasswordConfirm, None) - self.add_check(self.pw, self._checkPasswordConfirm, None) + # fields change. Separate checks are created on each field so that edits on + # either will trigger a check and so that the last edited field will get the focus + # when Done is clicked. Whichever check is run needs to run the other check in + # order to reset the status. The check_data field is used as a flag to prevent + # infinite recursion. + self._confirm_check = self.add_check(self.confirm, self._checkPasswordConfirm, None) + self._password_check = self.add_check(self.pw, self._checkPasswordConfirm, None)
# Keep a reference to this check, since it has to be manually run for the # click Done twice check. @@ -483,16 +487,31 @@ class UserSpoke(FirstbootSpokeMixIn, NormalSpoke): else: return None
- def _checkPasswordConfirm(self, editable=None, data=None): + def _checkPasswordConfirm(self, editable=None, reset_status=None): """If the user has entered confirmation data, check whether it matches the password.""" + + # This check is triggered by changes to either the password field or the + # confirmation field. If this method is being run from a successful check + # to reset the status, just return success + if reset_status: + return None
# Skip the check if no password is required if (not self.usepassword.get_active()) or self._user.password_kickstarted: - return None + result = None elif self.confirm.get_text() and (self.pw.get_text() != self.confirm.get_text()): - return _("The passwords do not match.") + result = _("The passwords do not match.") else: - return None + result = None + + # If the check succeeded, reset the status of the other check object + if result is None: + if editable == self.confirm: + self._password_check.update_check_status(check_data=True) + else: + self._confirm_check.update_check_status(check_data=True) + + return result
def _checkPasswordStrength(self, editable=None, data=None): """Update the error message based on password strength.
On Wed, 2013-09-18 at 15:04 -0400, David Shea wrote:
The check for whether the password field and the password confirmation field match is run when either field is changed, since changes to either field will cause the state of the match to change. This was working correctly when a change to either field broke the match, but was not always working when a change fixed the match. The check object for the field not changed remained in a failure state, making it impossible to exit the spoke even though the password matched. This fixes that by manually running the check on the field not changed.
pyanaconda/ui/gui/__init__.py | 11 +++++++++-- pyanaconda/ui/gui/spokes/user.py | 33 ++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index 7f18c4b..f971794 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -98,9 +98,16 @@ class GUICheck(object): self._handler_id = None self._check_status = None
- def update_check_status(self, editable=None, data=None):
- def update_check_status(self, editable=None, check_data=None): """Run an input validation check."""
new_check_status = self._run_check(self._editable, self._check_data)
# Allow check parameters to be overriden in parametersif editable is None:editable = self._editableif check_data is None:check_data = self._check_datanew_check_status = self._run_check(editable, check_data) check_status_changed = (self._check_status != new_check_status) self._check_status = new_check_statusdiff --git a/pyanaconda/ui/gui/spokes/user.py b/pyanaconda/ui/gui/spokes/user.py index 1ee9399..dd2d217 100644 --- a/pyanaconda/ui/gui/spokes/user.py +++ b/pyanaconda/ui/gui/spokes/user.py @@ -279,9 +279,13 @@ class UserSpoke(FirstbootSpokeMixIn, NormalSpoke): self.add_check(self.pw, self._checkPasswordEmpty, None)
# The password confirmation needs to be checked whenever either of the password
# fields changeself.add_check(self.confirm, self._checkPasswordConfirm, None)self.add_check(self.pw, self._checkPasswordConfirm, None)
# fields change. Separate checks are created on each field so that edits on# either will trigger a check and so that the last edited field will get the focus# when Done is clicked. Whichever check is run needs to run the other check in# order to reset the status. The check_data field is used as a flag to prevent# infinite recursion.self._confirm_check = self.add_check(self.confirm, self._checkPasswordConfirm, None)self._password_check = self.add_check(self.pw, self._checkPasswordConfirm, None) # Keep a reference to this check, since it has to be manually run for the # click Done twice check.@@ -483,16 +487,31 @@ class UserSpoke(FirstbootSpokeMixIn, NormalSpoke): else: return None
- def _checkPasswordConfirm(self, editable=None, data=None):
def _checkPasswordConfirm(self, editable=None, reset_status=None): """If the user has entered confirmation data, check whether it matches the password."""
# This check is triggered by changes to either the password field or the# confirmation field. If this method is being run from a successful check# to reset the status, just return successif reset_status:return None # Skip the check if no password is required if (not self.usepassword.get_active()) or self._user.password_kickstarted:
return None
result = None elif self.confirm.get_text() and (self.pw.get_text() != self.confirm.get_text()):
return _("The passwords do not match.")
result = _("The passwords do not match.") else:
return None
result = None# If the check succeeded, reset the status of the other check objectif result is None:if editable == self.confirm:self._password_check.update_check_status(check_data=True)else:self._confirm_check.update_check_status(check_data=True)return resultdef _checkPasswordStrength(self, editable=None, data=None): """Update the error message based on password strength.
Looks good to me.
anaconda-patches@lists.fedorahosted.org