summaryrefslogtreecommitdiffstats
path: root/src/gui/util/qvalidator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/util/qvalidator.cpp')
-rw-r--r--src/gui/util/qvalidator.cpp201
1 files changed, 95 insertions, 106 deletions
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 00e52f31e4..2a81006657 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qdebug.h>
@@ -367,12 +331,12 @@ QIntValidator::~QIntValidator()
or is a prefix of an integer in the valid range, returns \l Intermediate.
Otherwise, returns \l Invalid.
- If the valid range consists of just positive integers (e.g., 32 to 100)
- and \a input is a negative integer, then Invalid is returned. (On the other
- hand, if the range consists of negative integers (e.g., -100 to -32) and
- \a input is a positive integer, then Intermediate is returned, because
- the user might be just about to type the minus (especially for right-to-left
- languages).
+ If the valid range consists of just positive integers (e.g., 32 to 100) and
+ \a input is a negative integer, then Invalid is returned. (On the other
+ hand, if the range consists of negative integers (e.g., -100 to -32) and \a
+ input is a positive integer without leading plus sign, then Intermediate is
+ returned, because the user might be just about to type the minus (especially
+ for right-to-left languages).
Similarly, if the valid range is between 46 and 53, then 41 and 59 will be
evaluated as \l Intermediate, as otherwise the user wouldn't be able to
@@ -398,34 +362,45 @@ static qlonglong pow10(int exp)
return result;
}
-QValidator::State QIntValidator::validate(QString & input, int&) const
+template <typename T> static inline
+std::optional<QValidator::State> initialResultCheck(T min, T max, const ParsingResult &result)
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
- return Invalid;
- }
+ if (result.state == ParsingResult::Invalid)
+ return QValidator::Invalid;
+ const CharBuff &buff = result.buff;
if (buff.isEmpty())
- return Intermediate;
+ return QValidator::Intermediate;
- const bool startsWithMinus(buff[0] == '-');
- if (b >= 0 && startsWithMinus)
- return Invalid;
+ char ch = buff[0];
+ const bool signConflicts = (min >= 0 && ch == '-') || (max < 0 && ch == '+');
+ if (signConflicts)
+ return QValidator::Invalid;
- const bool startsWithPlus(buff[0] == '+');
- if (t < 0 && startsWithPlus)
- return Invalid;
+ if (result.state == ParsingResult::Intermediate)
+ return QValidator::Intermediate;
- if (buff.size() == 1 && (startsWithPlus || startsWithMinus))
- return Intermediate;
+ return std::nullopt;
+}
- bool ok;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
- if (!ok)
+QValidator::State QIntValidator::validate(QString & input, int&) const
+{
+ ParsingResult result =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
+
+ std::optional<State> opt = initialResultCheck(b, t, result);
+ if (opt)
+ return *opt;
+
+ const CharBuff &buff = result.buff;
+ QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10);
+ if (!r.ok())
return Invalid;
+ qint64 entered = r.result;
if (entered >= b && entered <= t) {
+ bool ok = false;
locale().toInt(input, &ok);
return ok ? Acceptable : Intermediate;
}
@@ -437,7 +412,7 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
// of a number of digits equal to or less than the max value as intermediate.
int buffLength = buff.size();
- if (startsWithPlus)
+ if (buff[0] == '+')
buffLength--;
const int tLength = t != 0 ? static_cast<int>(std::log10(qAbs(t))) + 1 : 1;
@@ -450,15 +425,15 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
/*! \reimp */
void QIntValidator::fixup(QString &input) const
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
+ auto [parseState, buff] =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
+ if (parseState == ParsingResult::Invalid)
return;
- }
- bool ok;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
- if (ok)
- input = locale().toString(entered);
+
+ QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10);
+ if (r.ok())
+ input = locale().toString(r.result);
}
/*!
@@ -491,7 +466,7 @@ void QIntValidator::setRange(int bottom, int top)
\brief the validator's lowest acceptable value
By default, this property's value is derived from the lowest signed
- integer available (typically -2147483647).
+ integer available (-2147483648).
\sa setRange()
*/
@@ -505,7 +480,7 @@ void QIntValidator::setBottom(int bottom)
\brief the validator's highest acceptable value
By default, this property's value is derived from the highest signed
- integer available (typically 2147483647).
+ integer available (2147483647).
\sa setRange()
*/
@@ -567,10 +542,11 @@ public:
in the German locale, "1,234" will be accepted as the fractional number
1.234. In Arabic locales, QDoubleValidator will accept Arabic digits.
- \note The QLocale::NumberOptions set on the locale() also affect the
- way the number is interpreted. For example, since QLocale::RejectGroupSeparator
- is not set by default, the validator will accept group separators. It is thus
- recommended to use QLocale::toDouble() to obtain the numeric value.
+ \note The QLocale::NumberOptions set on the locale() also affect the way the
+ number is interpreted. For example, since QLocale::RejectGroupSeparator is
+ not set by default (except on the \c "C" locale), the validator will accept
+ group separators. If the string passes validation, pass it to
+ locale().toDouble() to obtain its numeric value.
\sa QIntValidator, QRegularExpressionValidator, QLocale::toDouble(), {Line Edits Example}
*/
@@ -580,10 +556,23 @@ public:
\since 4.3
This enum defines the allowed notations for entering a double.
- \value StandardNotation The string is written as a standard number
- (i.e. 0.015).
- \value ScientificNotation The string is written in scientific
- form. It may have an exponent part(i.e. 1.5E-2).
+ \value StandardNotation The string is written in the standard format, a
+ whole number part optionally followed by a separator
+ and fractional part, for example \c{"0.015"}.
+
+ \value ScientificNotation The string is written in scientific form, which
+ optionally appends an exponent part to the
+ standard format, for example \c{"1.5E-2"}.
+
+ The whole number part may, as usual, include a sign. This, along with the
+ separators for fractional part, exponent and any digit-grouping, depend on
+ locale. QDoubleValidator doesn't check the placement (which would also
+ depend on locale) of any digit-grouping separators it finds, but it will
+ reject input that contains them if \l QLocale::RejectGroupSeparator is set
+ in \c locale().numberOptions().
+
+ \sa QLocale::numberOptions(), QLocale::decimalPoint(),
+ QLocale::exponential(), QLocale::negativeSign()
*/
/*!
@@ -625,14 +614,14 @@ QDoubleValidator::~QDoubleValidator()
/*!
\fn QValidator::State QDoubleValidator::validate(QString &input, int &pos) const
- Returns \l Acceptable if the string \a input contains a double
- that is within the valid range and is in the correct format.
+ Returns \l Acceptable if the string \a input is in the correct format and
+ contains a double within the valid range.
- Returns \l Intermediate if \a input contains a double that is
- outside the range or is in the wrong format; e.g. is empty.
+ Returns \l Intermediate if \a input is in the wrong format or contains a
+ double outside the range.
- Returns \l Invalid if the \a input is not a double or with too many
- digits after the decimal point.
+ Returns \l Invalid if the \a input doesn't represent a double or has too
+ many digits after the decimal point.
Note: If the valid range consists of just positive doubles (e.g. 0.0 to 100.0)
and \a input is a negative double then \l Invalid is returned. If notation()
@@ -668,19 +657,12 @@ QValidator::State QDoubleValidator::validate(QString & input, int &) const
QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const
{
Q_Q(const QDoubleValidator);
- QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) {
- return QValidator::Invalid;
- }
-
- if (buff.isEmpty())
- return QValidator::Intermediate;
+ ParsingResult result =
+ locale.d->m_data->validateChars(input, numMode, q->dec, locale.numberOptions());
- if (q->b >= 0 && buff.startsWith('-'))
- return QValidator::Invalid;
-
- if (q->t < 0 && buff.startsWith('+'))
- return QValidator::Invalid;
+ std::optional<QValidator::State> opt = initialResultCheck(q->b, q->t, result);
+ if (opt)
+ return *opt;
bool ok = false;
double i = locale.toDouble(input, &ok); // returns 0.0 if !ok
@@ -694,7 +676,11 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
if (notation == QDoubleValidator::StandardNotation) {
double max = qMax(qAbs(q->b), qAbs(q->t));
qlonglong v;
- if (convertDoubleTo(max, &v)) {
+ // Need a whole number to pass to convertDoubleTo() or it fails. Use
+ // floor, as max is positive so this has the same number of digits
+ // before the decimal point, where qCeil() might take us up to a power
+ // of ten, adding a digit.
+ if (convertDoubleTo(qFloor(max), &v)) {
qlonglong n = pow10(numDigits(v));
// In order to get the highest possible number in the intermediate
// range we need to get 10 to the power of the number of digits
@@ -755,15 +741,16 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe
const QLocale &locale) const
{
Q_Q(const QDoubleValidator);
- QByteArray buff;
// Passing -1 as the number of decimals, because fixup() exists to improve
// an Intermediate value, if it can.
- if (!locale.d->m_data->validateChars(input, numMode, &buff, -1, locale.numberOptions()))
+ auto [parseState, buff] =
+ locale.d->m_data->validateChars(input, numMode, -1, locale.numberOptions());
+ if (parseState == ParsingResult::Invalid)
return;
- // buff now contains data in C locale.
+ // buff contains data in C locale.
bool ok = false;
- const double entered = buff.toDouble(&ok);
+ const double entered = QByteArrayView(buff).toDouble(&ok);
if (ok) {
// Here we need to adjust the output format accordingly
char mode;
@@ -787,7 +774,7 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe
if (eIndex < 0)
eIndex = buff.size();
precision = eIndex - (buff.contains('.') ? 1 : 0)
- - (buff.startsWith('-') || buff.startsWith('+') ? 1 : 0);
+ - (buff[0] == '-' || buff[0] == '+' ? 1 : 0);
}
// Use q->dec to limit the number of decimals, because we want the
// fixup() result to pass validate().
@@ -1067,4 +1054,6 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr
QT_END_NAMESPACE
+#include "moc_qvalidator.cpp"
+
#endif // QT_NO_VALIDATOR