Qt 6.x
The Qt SDK
•All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qvalidator.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include <qdebug.h>
6
7#include "qvalidator.h"
8#ifndef QT_NO_VALIDATOR
9#include "private/qobject_p.h"
10#include "private/qlocale_p.h"
11#include "private/qnumeric_p.h"
12
13#include <limits.h>
14#include <cmath>
15
17
160 Q_DECLARE_PUBLIC(QValidator)
161public:
163 {
164 }
165
167};
168
169
177{
178}
179
186{
187}
188
196{
197 Q_D(const QValidator);
198 return d->locale;
199}
200
210{
211 Q_D(QValidator);
212 if (d->locale != locale) {
213 d->locale = locale;
214 emit changed();
215 }
216}
217
251{
252}
253
254
297 : QIntValidator(INT_MIN, INT_MAX, parent)
298{
299}
300
301
307QIntValidator::QIntValidator(int minimum, int maximum,
308 QObject * parent)
310{
311 b = minimum;
312 t = maximum;
313}
314
315
321{
322 // nothing
323}
324
325
351{
352 if (n == 0)
353 return 1;
354 return (int)std::log10(double(n)) + 1;
355}
356
357static qlonglong pow10(int exp)
358{
359 qlonglong result = 1;
360 for (int i = 0; i < exp; ++i)
361 result *= 10;
362 return result;
363}
364
366{
367 QByteArray buff;
368 if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
369 locale().numberOptions())) {
370 return Invalid;
371 }
372
373 if (buff.isEmpty())
374 return Intermediate;
375
376 const bool startsWithMinus(buff[0] == '-');
377 if (b >= 0 && startsWithMinus)
378 return Invalid;
379
380 const bool startsWithPlus(buff[0] == '+');
381 if (t < 0 && startsWithPlus)
382 return Invalid;
383
384 if (buff.size() == 1 && (startsWithPlus || startsWithMinus))
385 return Intermediate;
386
387 bool ok;
388 qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
389 if (!ok)
390 return Invalid;
391
392 if (entered >= b && entered <= t) {
393 locale().toInt(input, &ok);
394 return ok ? Acceptable : Intermediate;
395 }
396
397 if (entered >= 0) {
398 // the -entered < b condition is necessary to allow people to type
399 // the minus last (e.g. for right-to-left languages)
400 // The buffLength > tLength condition validates values consisting
401 // of a number of digits equal to or less than the max value as intermediate.
402
403 int buffLength = buff.size();
404 if (startsWithPlus)
405 buffLength--;
406 const int tLength = t != 0 ? static_cast<int>(std::log10(qAbs(t))) + 1 : 1;
407
408 return (entered > t && -entered < b && buffLength > tLength) ? Invalid : Intermediate;
409 } else {
410 return (entered < b) ? Invalid : Intermediate;
411 }
412}
413
416{
417 QByteArray buff;
418 if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
419 locale().numberOptions())) {
420 return;
421 }
422 bool ok;
423 qlonglong entered = QLocaleData::bytearrayToLongLong(buff, 10, &ok);
424 if (ok)
425 input = locale().toString(entered);
426}
427
434{
435 bool rangeChanged = false;
436 if (b != bottom) {
437 b = bottom;
438 rangeChanged = true;
440 }
441
442 if (t != top) {
443 t = top;
444 rangeChanged = true;
446 }
447
448 if (rangeChanged)
449 emit changed();
450}
451
452
463{
464 setRange(bottom, top());
465}
466
477{
478 setRange(bottom(), top);
479}
480
485 : QObject(d, parent)
486{
487}
488
493 : QObject(d, parent)
494{
495}
496
498{
499 Q_DECLARE_PUBLIC(QDoubleValidator)
500public:
503 , notation(QDoubleValidator::ScientificNotation)
504 {
505 }
506
508
511 const QLocale &locale) const;
512};
513
514
573 : QDoubleValidator(-HUGE_VAL, HUGE_VAL, -1, parent)
574{
575}
576
577
584QDoubleValidator::QDoubleValidator(double bottom, double top, int decimals,
585 QObject * parent)
587{
588 b = bottom;
589 t = top;
590 dec = decimals;
591}
592
593
599{
600}
601
602
625#ifndef LLONG_MAX
626# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff)
627#endif
628
630{
631 Q_D(const QDoubleValidator);
632
634 switch (d->notation) {
635 case StandardNotation:
637 break;
640 break;
641 }
642
643 return d->validateWithLocale(input, numMode, locale());
644}
645
647{
648 Q_Q(const QDoubleValidator);
649 QByteArray buff;
650 if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) {
651 return QValidator::Invalid;
652 }
653
654 if (buff.isEmpty())
656
657 if (q->b >= 0 && buff.startsWith('-'))
658 return QValidator::Invalid;
659
660 if (q->t < 0 && buff.startsWith('+'))
661 return QValidator::Invalid;
662
663 bool ok = false;
664 double i = locale.toDouble(input, &ok); // returns 0.0 if !ok
665 Q_ASSERT(!qIsNaN(i)); // Would be caught by validateChars()
666 if (!ok)
668
669 if (i >= q->b && i <= q->t)
671
673 double max = qMax(qAbs(q->b), qAbs(q->t));
674 qlonglong v;
675 // Need a whole number to pass to convertDoubleTo() or it fails. Use
676 // floor, as max is positive so this has the same number of digits
677 // before the decimal point, where qCeil() might take us up to a power
678 // of ten, adding a digit.
679 if (convertDoubleTo(qFloor(max), &v)) {
681 // In order to get the highest possible number in the intermediate
682 // range we need to get 10 to the power of the number of digits
683 // after the decimal's and subtract that from the top number.
684 //
685 // For example, where q->dec == 2 and with a range of 0.0 - 9.0
686 // then the minimum possible number is 0.00 and the maximum
687 // possible is 9.99. Therefore 9.999 and 10.0 should be seen as
688 // invalid.
689 if (qAbs(i) > (n - std::pow(10, -q->dec)))
690 return QValidator::Invalid;
691 }
692 }
693
695}
696
728{
729 Q_D(const QDoubleValidator);
730 const auto numberMode = d->notation == StandardNotation ? QLocaleData::DoubleStandardMode
732
733 d->fixupWithLocale(input, numberMode, locale());
734}
735
737 const QLocale &locale) const
738{
739 Q_Q(const QDoubleValidator);
740 QByteArray buff;
741 // Passing -1 as the number of decimals, because fixup() exists to improve
742 // an Intermediate value, if it can.
743 if (!locale.d->m_data->validateChars(input, numMode, &buff, -1, locale.numberOptions()))
744 return;
745
746 // buff now contains data in C locale.
747 bool ok = false;
748 const double entered = buff.toDouble(&ok);
749 if (ok) {
750 // Here we need to adjust the output format accordingly
751 char mode;
752 if (numMode == QLocaleData::DoubleStandardMode) {
753 mode = 'f';
754 } else {
755 // scientific mode can be either 'e' or 'E'
756 mode = input.contains(QChar::fromLatin1('E')) ? 'E' : 'e';
757 }
758 int precision;
759 if (q->dec < 0) {
761 } else {
762 if (mode == 'f') {
763 const auto decimalPointIndex = buff.indexOf('.');
764 precision = decimalPointIndex >= 0 ? buff.size() - decimalPointIndex - 1 : 0;
765 } else {
766 auto eIndex = buff.indexOf('e');
767 // No need to check for 'E' because we can get only 'e' after a
768 // call to validateChars()
769 if (eIndex < 0)
770 eIndex = buff.size();
771 precision = eIndex - (buff.contains('.') ? 1 : 0)
772 - (buff.startsWith('-') || buff.startsWith('+') ? 1 : 0);
773 }
774 // Use q->dec to limit the number of decimals, because we want the
775 // fixup() result to pass validate().
776 precision = qMin(precision, q->dec);
777 }
778 input = locale.toString(entered, mode, precision);
779 }
780}
781
791void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
792{
793 bool rangeChanged = false;
794 if (b != minimum) {
795 b = minimum;
796 rangeChanged = true;
798 }
799
800 if (t != maximum) {
801 t = maximum;
802 rangeChanged = true;
804 }
805
806 if (dec != decimals) {
807 dec = decimals;
808 rangeChanged = true;
810 }
811 if (rangeChanged)
812 emit changed();
813}
814
821void QDoubleValidator::setRange(double minimum, double maximum)
822{
823 setRange(minimum, maximum, decimals());
824}
825
836{
838}
839
840
851{
853}
854
866{
868}
869
881{
882 Q_D(QDoubleValidator);
883 if (d->notation != newNotation) {
884 d->notation = newNotation;
885 emit notationChanged(d->notation);
886 emit changed();
887 }
888}
889
891{
892 Q_D(const QDoubleValidator);
893 return d->notation;
894}
895
896#if QT_CONFIG(regularexpression)
897
930class QRegularExpressionValidatorPrivate : public QValidatorPrivate
931{
932 Q_DECLARE_PUBLIC(QRegularExpressionValidator)
933
934public:
935 QRegularExpression origRe; // the one set by the user
936 QRegularExpression usedRe; // the one actually used
937 void setRegularExpression(const QRegularExpression &re);
938};
939
945QRegularExpressionValidator::QRegularExpressionValidator(QObject *parent)
946 : QValidator(*new QRegularExpressionValidatorPrivate, parent)
947{
948 // origRe in the private will be an empty QRegularExpression,
949 // and therefore this validator will match any string.
950}
951
957QRegularExpressionValidator::QRegularExpressionValidator(const QRegularExpression &re, QObject *parent)
958 : QRegularExpressionValidator(parent)
959{
960 Q_D(QRegularExpressionValidator);
961 d->setRegularExpression(re);
962}
963
964
969QRegularExpressionValidator::~QRegularExpressionValidator()
970{
971}
972
989QValidator::State QRegularExpressionValidator::validate(QString &input, int &pos) const
990{
991 Q_D(const QRegularExpressionValidator);
992
993 // We want a validator with an empty QRegularExpression to match anything;
994 // since we're going to do an exact match (by using d->usedRe), first check if the rx is empty
995 // (and, if so, accept the input).
996 if (d->origRe.pattern().isEmpty())
997 return Acceptable;
998
1000 if (m.hasMatch()) {
1001 return Acceptable;
1002 } else if (input.isEmpty() || m.hasPartialMatch()) {
1003 return Intermediate;
1004 } else {
1005 pos = input.size();
1006 return Invalid;
1007 }
1008}
1009
1018QRegularExpression QRegularExpressionValidator::regularExpression() const
1019{
1020 Q_D(const QRegularExpressionValidator);
1021 return d->origRe;
1022}
1023
1024void QRegularExpressionValidator::setRegularExpression(const QRegularExpression &re)
1025{
1026 Q_D(QRegularExpressionValidator);
1027 d->setRegularExpression(re);
1028}
1029
1036void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpression &re)
1037{
1038 Q_Q(QRegularExpressionValidator);
1039
1040 if (origRe != re) {
1041 usedRe = origRe = re; // copies also the pattern options
1043 emit q->regularExpressionChanged(re);
1044 emit q->changed();
1045 }
1046}
1047
1048#endif // QT_CONFIG(regularexpression)
1049
1051
1052#include "moc_qvalidator.cpp"
1053
1054#endif // QT_NO_VALIDATOR
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
double toDouble(bool *ok=nullptr) const
Returns the byte array converted to a double value.
bool startsWith(QByteArrayView bv) const
Definition qbytearray.h:170
bool contains(char c) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:583
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static constexpr QChar fromLatin1(char c) noexcept
Converts the Latin-1 character c to its equivalent QChar.
Definition qchar.h:461
QValidator::State validateWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const
void fixupWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const
QDoubleValidator::Notation notation
The QDoubleValidator class provides range checking of floating-point numbers.
Definition qvalidator.h:89
void bottomChanged(double bottom)
This signal is emitted after the bottom property changed.
double bottom
the validator's minimum acceptable value
Definition qvalidator.h:91
void setBottom(double)
void decimalsChanged(int decimals)
This signal is emitted after the decimals property changed.
Notation notation
the notation of how a string can describe a number
Definition qvalidator.h:94
~QDoubleValidator()
Destroys the validator.
QDoubleValidator(QObject *parent=nullptr)
Constructs a validator object with a parent object that accepts any double.
void notationChanged(QDoubleValidator::Notation notation)
This signal is emitted after the notation property changed.
QValidator::State validate(QString &, int &) const override
Returns \l Acceptable if the string input is in the correct format and contains a double within the v...
void setRange(double bottom, double top, int decimals)
Sets the validator to accept doubles from minimum to maximum inclusive, with at most decimals digits ...
int decimals
the validator's maximum number of digits after the decimal point
Definition qvalidator.h:93
void setTop(double)
void setNotation(Notation)
void topChanged(double top)
This signal is emitted after the top property changed.
double top
the validator's maximum acceptable value
Definition qvalidator.h:92
void setDecimals(int)
void fixup(QString &input) const override
The QIntValidator class provides a validator that ensures a string contains a valid integer within a ...
Definition qvalidator.h:56
void topChanged(int top)
This signal is emitted after the top property changed.
void setRange(int bottom, int top)
Sets the range of the validator to only accept integers between bottom and top inclusive.
int bottom
the validator's lowest acceptable value
Definition qvalidator.h:58
QValidator::State validate(QString &, int &) const override
Returns \l Acceptable if the input is an integer within the valid range.
void fixup(QString &input) const override
\reimp
void setTop(int)
int top
the validator's highest acceptable value
Definition qvalidator.h:59
void setBottom(int)
QIntValidator(QObject *parent=nullptr)
Constructs a validator with a parent object that accepts all integers.
void bottomChanged(int bottom)
This signal is emitted after the bottom property changed.
~QIntValidator()
Destroys the validator.
const QLocaleData *const m_data
Definition qlocale_p.h:512
double toDouble(const QString &s, bool *ok=nullptr) const
Returns the double represented by the localized string s.
Definition qlocale.h:950
@ FloatingPointShortest
Definition qlocale.h:880
int toInt(const QString &s, bool *ok=nullptr) const
Returns the int represented by the localized string s.
Definition qlocale.h:936
QString toString(qlonglong i) const
Returns a localized string representation of i.
Definition qlocale.cpp:1962
NumberOptions numberOptions() const
Definition qlocale.cpp:1155
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
void setPattern(const QString &pattern)
Sets the pattern string of the regular expression to pattern.
QString pattern() const
Returns the pattern string of the regular expression.
static QString anchoredPattern(const QString &expression)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
The QValidator class provides validation of input text.
Definition qvalidator.h:24
void setLocale(const QLocale &locale)
Sets the locale that will be used for the validator.
State
This enum type defines the states in which a validated string can exist.
Definition qvalidator.h:30
virtual void fixup(QString &) const
This function attempts to change input to be valid according to this validator's rules.
QValidator(QObject *parent=nullptr)
Sets up the validator.
QLocale locale() const
Returns the locale for the validator.
~QValidator()
Destroys the validator, freeing any storage and other resources used.
void changed()
This signal is emitted when any property that may affect the validity of a string has changed.
Combined button and popup list for selecting options.
bool qIsNaN(qfloat16 f) noexcept
Definition qfloat16.h:238
int qFloor(T v)
Definition qmath.h:42
@ Invalid
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLenum mode
const GLfloat * m
GLdouble GLdouble GLdouble GLdouble top
GLint GLint bottom
GLfloat n
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLenum GLenum GLenum input
GLenum GLint GLint * precision
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
qint64 qlonglong
Definition qtypes.h:58
static qlonglong pow10(int exp)
static int numDigits(qlonglong n)
Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits=-1, QLocale::NumberOptions number_options=QLocale::DefaultNumberOptions) const
Definition qlocale.cpp:4204
@ DoubleScientificMode
Definition qlocale_p.h:248
@ DoubleStandardMode
Definition qlocale_p.h:248
static Q_CORE_EXPORT qint64 bytearrayToLongLong(QByteArrayView num, int base, bool *ok)
Definition qlocale.cpp:4352
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent