diff options
-rw-r--r-- | src/gui/widgets/qspinbox.cpp | 214 | ||||
-rw-r--r-- | tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp | 45 | ||||
-rw-r--r-- | tests/auto/qspinbox/tst_qspinbox.cpp | 8 |
3 files changed, 45 insertions, 222 deletions
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index a2e4c15..8d21f3f 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE # define QSBDEBUG if (false) qDebug #endif -static bool isIntermediateValueHelper(qint64 num, qint64 minimum, qint64 maximum, qint64 *match = 0); - class QSpinBoxPrivate : public QAbstractSpinBoxPrivate { Q_DECLARE_PUBLIC(QSpinBox) @@ -73,7 +71,6 @@ public: virtual QString textFromValue(const QVariant &n) const; QVariant validateAndInterpret(QString &input, int &pos, QValidator::State &state) const; - bool isIntermediateValue(const QString &str) const; QChar thousand; inline void init() { @@ -87,7 +84,6 @@ class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate public: QDoubleSpinBoxPrivate(QWidget *parent = 0); void emitSignals(EmitPolicy ep, const QVariant &); - bool isIntermediateValue(const QString &str) const; virtual QVariant valueFromText(const QString &n) const; virtual QString textFromValue(const QVariant &n) const; @@ -975,51 +971,6 @@ QVariant QSpinBoxPrivate::valueFromText(const QString &text) const /*! - \internal - - Return true if str can become a number which is between minimum and - maximum or false if this is not possible. -*/ - -bool QSpinBoxPrivate::isIntermediateValue(const QString &str) const -{ - const int num = q_func()->locale().toInt(str, 0, 10); - const int min = minimum.toInt(); - const int max = maximum.toInt(); - - int numDigits = 0; - int digits[10]; - int tmp = num; - if (tmp == 0) { - numDigits = 1; - digits[0] = 0; - } else { - tmp = num; - for (int i=0; tmp != 0; ++i) { - digits[numDigits++] = qAbs(tmp % 10); - tmp /= 10; - } - } - - int failures = 0; - for (int number=min; /*number<=max*/; ++number) { - tmp = number; - for (int i=0; tmp != 0;) { - if (digits[i] == qAbs(tmp % 10)) { - if (++i == numDigits) - return true; - } - tmp /= 10; - } - if (failures++ == 500000) //upper bound - return true; - if (number == max) // needed for INT_MAX - break; - } - return false; -} - -/*! \internal Multi purpose function that parses input, sets state to the appropriate state and returns the value it will be interpreted as. @@ -1073,9 +1024,8 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; } else { - state = isIntermediateValue(copy) ? QValidator::Intermediate : QValidator::Invalid; - QSBDEBUG() << __FILE__ << __LINE__<< "state is set to " - << (state == QValidator::Intermediate ? "Intermediate" : "Acceptable"); + state = QValidator::Intermediate; + QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate"; } } } @@ -1135,105 +1085,6 @@ void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old) } -bool QDoubleSpinBoxPrivate::isIntermediateValue(const QString &str) const -{ - QSBDEBUG() << "input is" << str << minimum << maximum; - qint64 dec = 1; - for (int i=0; i<decimals; ++i) - dec *= 10; - - const QLatin1Char dot('.'); - - // I know QString::number() uses CLocale so I use dot - const QString minstr = QString::number(minimum.toDouble(), 'f', decimals); - bool ok; - qint64 min_left = minstr.left(minstr.indexOf(dot)).toLongLong(&ok); - if (!ok) - return false; - qint64 min_right = minstr.mid(minstr.indexOf(dot) + 1).toLongLong(); - - const QString maxstr = QString::number(maximum.toDouble(), 'f', decimals); - qint64 max_left = maxstr.left(maxstr.indexOf(dot)).toLongLong(&ok); - if (!ok) - return true; - qint64 max_right = maxstr.mid(maxstr.indexOf(dot) + 1).toLongLong(); - - const int dotindex = str.indexOf(delimiter); - const bool negative = maximum.toDouble() < 0; - qint64 left = 0, right = 0; - bool doleft = true; - bool doright = true; - if (dotindex == -1) { - left = str.toLongLong(); - doright = false; - } else if (dotindex == 0 || (dotindex == 1 && str.at(0) == QLatin1Char('+'))) { - if (negative) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - doleft = false; - right = str.mid(dotindex + 1).toLongLong(); - } else if (dotindex == 1 && str.at(0) == QLatin1Char('-')) { - if (!negative) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - doleft = false; - right = str.mid(dotindex + 1).toLongLong(); - } else { - left = str.left(dotindex).toLongLong(); - if (dotindex == str.size() - 1) { - doright = false; - } else { - right = str.mid(dotindex + 1).toLongLong(); - } - } - if ((left >= 0 && max_left < 0 && !str.startsWith(QLatin1Char('-'))) || (left < 0 && min_left >= 0)) { - QSBDEBUG("returns false 0"); - return false; - } - - qint64 match = min_left; - if (doleft && !isIntermediateValueHelper(left, min_left, max_left, &match)) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - if (doright) { - QSBDEBUG("match %lld min_left %lld max_left %lld", match, min_left, max_left); - if (!doleft) { - if (min_left == max_left) { - const bool ret = isIntermediateValueHelper(qAbs(left), - negative ? max_right : min_right, - negative ? min_right : max_right); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } else if (qAbs(max_left - min_left) == 1) { - const bool ret = isIntermediateValueHelper(qAbs(left), min_right, negative ? 0 : dec) - || isIntermediateValueHelper(qAbs(left), negative ? dec : 0, max_right); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } else { - const bool ret = isIntermediateValueHelper(qAbs(left), 0, dec); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } - } - if (match != min_left) { - min_right = negative ? dec : 0; - } - if (match != max_left) { - max_right = negative ? 0 : dec; - } - qint64 tmpl = negative ? max_right : min_right; - qint64 tmpr = negative ? min_right : max_right; - const bool ret = isIntermediateValueHelper(right, tmpl, tmpr); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } - QSBDEBUG() << __FILE__ << __LINE__ << "returns true"; - return true; -} - /*! \internal \reimp @@ -1402,9 +1253,8 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; } else { - state = isIntermediateValue(copy) ? QValidator::Intermediate : QValidator::Invalid; - QSBDEBUG() << __FILE__ << __LINE__<< "state is set to " - << (state == QValidator::Intermediate ? "Intermediate" : "Acceptable"); + state = QValidator::Intermediate; + QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate"; } } } @@ -1462,62 +1312,6 @@ QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const Use minimum() instead. */ -/*! - \internal Returns whether \a str is a string which value cannot be - parsed but still might turn into something valid. -*/ - -static bool isIntermediateValueHelper(qint64 num, qint64 min, qint64 max, qint64 *match) -{ - QSBDEBUG("%lld %lld %lld", num, min, max); - - if (num >= min && num <= max) { - if (match) - *match = num; - QSBDEBUG("returns true 0"); - return true; - } - qint64 tmp = num; - - int numDigits = 0; - int digits[10]; - if (tmp == 0) { - numDigits = 1; - digits[0] = 0; - } else { - tmp = qAbs(num); - for (int i=0; tmp > 0; ++i) { - digits[numDigits++] = tmp % 10; - tmp /= 10; - } - } - - int failures = 0; - qint64 number; - for (number=max; number>=min; --number) { - tmp = qAbs(number); - for (int i=0; tmp > 0;) { - if (digits[i] == (tmp % 10)) { - if (++i == numDigits) { - if (match) - *match = number; - QSBDEBUG("returns true 1"); - return true; - } - } - tmp /= 10; - } - if (failures++ == 500000) { //upper bound - if (match) - *match = num; - QSBDEBUG("returns true 2"); - return true; - } - } - QSBDEBUG("returns false"); - return false; -} - /*! \reimp */ bool QSpinBox::event(QEvent *event) { diff --git a/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp index dada015..1fb0e1e 100644 --- a/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/qdoublespinbox/tst_qdoublespinbox.cpp @@ -52,6 +52,9 @@ #include <qlineedit.h> #include <qdebug.h> + +#include "../../shared/util.h" + //TESTED_CLASS= //TESTED_FILES=gui/widgets/qspinbox.h gui/widgets/qspinbox.cpp gui/widgets/qabstractspinbox.cpp gui/widgets/qabstractspinbox_p.h gui/widgets/qabstractspinbox.h @@ -142,6 +145,7 @@ private slots: void task224497_fltMax(); void task221221(); + void task255471_decimalsValidation(); public slots: void valueChangedHelper(const QString &); @@ -665,7 +669,7 @@ void tst_QDoubleSpinBox::valueFromTextAndValidate_data() QTest::addColumn<int>("language"); QTest::addColumn<QString>("expectedText"); // if empty we don't check - QTest::newRow("data0") << QString("2.2") << Invalid << 3.0 << 5.0 << (int)QLocale::C << QString(); + QTest::newRow("data0") << QString("2.2") << Intermediate << 3.0 << 5.0 << (int)QLocale::C << QString(); QTest::newRow("data1") << QString() << Intermediate << 0.0 << 100.0 << (int)QLocale::C << QString(); QTest::newRow("data2") << QString("asd") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString(); QTest::newRow("data3") << QString("2.2") << Acceptable << 0.0 << 100.0 << (int)QLocale::C << QString(); @@ -682,20 +686,20 @@ void tst_QDoubleSpinBox::valueFromTextAndValidate_data() QTest::newRow("data14") << QString("1, ") << Acceptable << 0.0 << 100.0 << (int)QLocale::Norwegian << QString("1,"); QTest::newRow("data15") << QString("1, ") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString(); QTest::newRow("data16") << QString("2") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString(); - QTest::newRow("data17") << QString("22.0") << Invalid << 100.0 << 102.0 << (int)QLocale::C << QString(); + QTest::newRow("data17") << QString("22.0") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString(); QTest::newRow("data18") << QString("12.0") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString(); - QTest::newRow("data19") << QString("12.2") << Invalid << 100. << 102.0 << (int)QLocale::C << QString(); - QTest::newRow("data20") << QString("21.") << Invalid << 100.0 << 102.0 << (int)QLocale::C << QString(); - QTest::newRow("data21") << QString("-21.") << Invalid << -102.0 << -100.0 << (int)QLocale::C << QString(); + QTest::newRow("data19") << QString("12.2") << Intermediate << 100. << 102.0 << (int)QLocale::C << QString(); + QTest::newRow("data20") << QString("21.") << Intermediate << 100.0 << 102.0 << (int)QLocale::C << QString(); + QTest::newRow("data21") << QString("-21.") << Intermediate << -102.0 << -100.0 << (int)QLocale::C << QString(); QTest::newRow("data22") << QString("-12.") << Intermediate << -102.0 << -100.0 << (int)QLocale::C << QString(); - QTest::newRow("data23") << QString("-11.11") << Invalid << -102.0 << -101.2 << (int)QLocale::C << QString(); + QTest::newRow("data23") << QString("-11.11") << Intermediate << -102.0 << -101.2 << (int)QLocale::C << QString(); QTest::newRow("data24") << QString("-11.4") << Intermediate << -102.0 << -101.3 << (int)QLocale::C << QString(); QTest::newRow("data25") << QString("11.400") << Invalid << 0.0 << 100.0 << (int)QLocale::C << QString(); QTest::newRow("data26") << QString(".4") << Intermediate << 0.45 << 0.5 << (int)QLocale::C << QString(); QTest::newRow("data27") << QString("+.4") << Intermediate << 0.45 << 0.5 << (int)QLocale::C << QString(); QTest::newRow("data28") << QString("-.4") << Intermediate << -0.5 << -0.45 << (int)QLocale::C << QString(); QTest::newRow("data29") << QString(".4") << Intermediate << 1.0 << 2.4 << (int)QLocale::C << QString(); - QTest::newRow("data30") << QString("-.4") << Invalid << -2.3 << -1.9 << (int)QLocale::C << QString(); + QTest::newRow("data30") << QString("-.4") << Intermediate << -2.3 << -1.9 << (int)QLocale::C << QString(); QTest::newRow("data31") << QString("-42") << Invalid << -2.43 << -1.0 << (int)QLocale::C << QString(); QTest::newRow("data32") << QString("-4") << Invalid << -1.4 << -1.0 << (int)QLocale::C << QString(); QTest::newRow("data33") << QString("-42") << Invalid << -1.4 << -1.0 << (int)QLocale::C << QString(); @@ -709,7 +713,7 @@ void tst_QDoubleSpinBox::valueFromTextAndValidate_data() QTest::newRow("data41") << QString("103.") << Invalid << -102.0 << 11.0 << (int)QLocale::C << QString(); QTest::newRow("data42") << QString("122") << Invalid << 10.0 << 12.2 << (int)QLocale::C << QString(); QTest::newRow("data43") << QString("-2.2") << Intermediate << -12.2 << -3.2 << (int)QLocale::C << QString(); - QTest::newRow("data44") << QString("-2.20") << Invalid << -12.1 << -3.2 << (int)QLocale::C << QString(); + QTest::newRow("data44") << QString("-2.20") << Intermediate << -12.1 << -3.2 << (int)QLocale::C << QString(); QTest::newRow("data45") << QString("200,2") << Invalid << 0.0 << 1000.0 << (int)QLocale::C << QString(); QTest::newRow("data46") << QString("200,2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::German << QString(); QTest::newRow("data47") << QString("2.2") << Acceptable << 0.0 << 1000.0 << (int)QLocale::C << QString(); @@ -1003,6 +1007,31 @@ void tst_QDoubleSpinBox::task221221() QCOMPARE(spin.text(), QLatin1String("1")); } +void tst_QDoubleSpinBox::task255471_decimalsValidation() +{ + // QDoubleSpinBox shouldn't crash with large numbers of decimals. Even if + // the results are useless ;-) + for (int i = 0; i < 32; ++i) + { + QDoubleSpinBox spinBox; + spinBox.setDecimals(i); + spinBox.setMinimum(0.3); + spinBox.setMaximum(12); + + spinBox.show(); + QTRY_VERIFY(spinBox.isVisible()); + spinBox.setFocus(); + QTRY_VERIFY(spinBox.hasFocus()); + + QTest::keyPress(&spinBox, Qt::Key_Right); + QTest::keyPress(&spinBox, Qt::Key_Right); + QTest::keyPress(&spinBox, Qt::Key_Delete); + + // Don't crash! + QTest::keyPress(&spinBox, Qt::Key_2); + } +} + QTEST_MAIN(tst_QDoubleSpinBox) #include "tst_qdoublespinbox.moc" diff --git a/tests/auto/qspinbox/tst_qspinbox.cpp b/tests/auto/qspinbox/tst_qspinbox.cpp index 9f00be6..79e3ca7 100644 --- a/tests/auto/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/qspinbox/tst_qspinbox.cpp @@ -643,21 +643,21 @@ void tst_QSpinBox::valueFromTextAndValidate_data() QTest::addColumn<int>("maxi"); QTest::addColumn<QString>("expectedText"); // if empty we don't check - QTest::newRow("data0") << QString("2") << Invalid << 3 << 5 << QString(); + QTest::newRow("data0") << QString("2") << Intermediate << 3 << 5 << QString(); QTest::newRow("data1") << QString() << Intermediate << 0 << 100 << QString(); QTest::newRow("data2") << QString("asd") << Invalid << 0 << 100 << QString(); QTest::newRow("data3") << QString("2") << Acceptable << 0 << 100 << QString(); QTest::newRow("data4") << QString() << Intermediate << 0 << 1 << QString(); QTest::newRow("data5") << QString() << Invalid << 0 << 0 << QString(); QTest::newRow("data5") << QString("5") << Intermediate << 2004 << 2005 << QString(); - QTest::newRow("data6") << QString("50") << Invalid << 2004 << 2005 << QString(); + QTest::newRow("data6") << QString("50") << Intermediate << 2004 << 2005 << QString(); QTest::newRow("data7") << QString("205") << Intermediate << 2004 << 2005 << QString(); QTest::newRow("data8") << QString("2005") << Acceptable << 2004 << 2005 << QString(); - QTest::newRow("data9") << QString("3") << Invalid << 2004 << 2005 << QString(); + QTest::newRow("data9") << QString("3") << Intermediate << 2004 << 2005 << QString(); QTest::newRow("data10") << QString("-") << Intermediate << -20 << -10 << QString(); QTest::newRow("data11") << QString("-1") << Intermediate << -20 << -10 << QString(); QTest::newRow("data12") << QString("-5") << Intermediate << -20 << -10 << QString(); - QTest::newRow("data13") << QString("-5") << Invalid << -20 << -16 << QString(); + QTest::newRow("data13") << QString("-5") << Intermediate << -20 << -16 << QString(); QTest::newRow("data14") << QString("-2") << Intermediate << -20 << -16 << QString(); QTest::newRow("data15") << QString("2") << Invalid << -20 << -16 << QString(); QTest::newRow("data16") << QString() << Intermediate << -20 << -16 << QString(); |