diff --git a/examples/widgets/widgets/spinboxes/window.cpp b/examples/widgets/widgets/spinboxes/window.cpp index 8c35f93c56..acce642ec6 100644 --- a/examples/widgets/widgets/spinboxes/window.cpp +++ b/examples/widgets/widgets/spinboxes/window.cpp @@ -94,6 +94,14 @@ void Window::createSpinBoxes() priceSpinBox->setValue(99); //! [4] //! [5] + QLabel *hexLabel = new QLabel(tr("Enter a value between " + "%1 and %2:").arg('-' + QString::number(31, 16)).arg(QString::number(31, 16))); + QSpinBox *hexSpinBox = new QSpinBox; + hexSpinBox->setRange(-31, 31); + hexSpinBox->setSingleStep(1); + hexSpinBox->setValue(0); + hexSpinBox->setDisplayIntegerBase(16); + QVBoxLayout *spinBoxLayout = new QVBoxLayout; spinBoxLayout->addWidget(integerLabel); spinBoxLayout->addWidget(integerSpinBox); @@ -101,6 +109,8 @@ void Window::createSpinBoxes() spinBoxLayout->addWidget(zoomSpinBox); spinBoxLayout->addWidget(priceLabel); spinBoxLayout->addWidget(priceSpinBox); + spinBoxLayout->addWidget(hexLabel); + spinBoxLayout->addWidget(hexSpinBox); spinBoxesGroup->setLayout(spinBoxLayout); } //! [5] diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 0ce5473ad8..bf4e130d4e 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -78,6 +78,8 @@ public: q->setInputMethodHints(Qt::ImhDigitsOnly); setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem); } + + int displayIntegerBase; }; class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate @@ -424,6 +426,38 @@ void QSpinBox::setRange(int minimum, int maximum) d->setRange(QVariant(minimum), QVariant(maximum)); } +/*! + \property QSpinBox::displayIntegerBase + + \brief the base used to display the value of the spin box + + The default displayIntegerBase value is 10. + + \sa textFromValue(), valueFromText() + \since 5.2 +*/ + +int QSpinBox::displayIntegerBase() const +{ + Q_D(const QSpinBox); + return d->displayIntegerBase; +} + +void QSpinBox::setDisplayIntegerBase(int base) +{ + Q_D(QSpinBox); + // Falls back to base 10 on invalid bases (like QString) + if (base < 2 || base > 36) { + qWarning("QSpinBox::setDisplayIntegerBase: Invalid base (%d)", base); + base = 10; + } + + if (base != d->displayIntegerBase) { + d->displayIntegerBase = base; + d->updateEdit(); + } +} + /*! This virtual function is used by the spin box whenever it needs to display the given \a value. The default implementation returns a @@ -444,9 +478,18 @@ void QSpinBox::setRange(int minimum, int maximum) QString QSpinBox::textFromValue(int value) const { - QString str = locale().toString(value); - if (qAbs(value) >= 1000 || value == INT_MIN) { - str.remove(locale().groupSeparator()); + Q_D(const QSpinBox); + QString str; + + if (d->displayIntegerBase != 10) { + str = QString::number(qAbs(value), d->displayIntegerBase); + if (value < 0) + str.prepend('-'); + } else { + str = locale().toString(value); + if (qAbs(value) >= 1000 || value == INT_MIN) { + str.remove(locale().groupSeparator()); + } } return str; @@ -926,6 +969,7 @@ QSpinBoxPrivate::QSpinBoxPrivate() minimum = QVariant((int)0); maximum = QVariant((int)99); value = minimum; + displayIntegerBase = 10; singleStep = QVariant((int)1); type = QVariant::Int; } @@ -1003,11 +1047,15 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100 } else { bool ok = false; - num = locale.toInt(copy, &ok); - if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) { - QString copy2 = copy; - copy2.remove(locale.groupSeparator()); - num = locale.toInt(copy2, &ok); + if (displayIntegerBase != 10) { + num = copy.toInt(&ok, displayIntegerBase); + } else { + num = locale.toInt(copy, &ok); + if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) { + QString copy2 = copy; + copy2.remove(locale.groupSeparator()); + num = locale.toInt(copy2, &ok); + } } QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num; if (!ok) { diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h index 4963f87a1a..98e809e141 100644 --- a/src/widgets/widgets/qspinbox.h +++ b/src/widgets/widgets/qspinbox.h @@ -61,6 +61,7 @@ class Q_WIDGETS_EXPORT QSpinBox : public QAbstractSpinBox Q_PROPERTY(int maximum READ maximum WRITE setMaximum) Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep) Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true) + Q_PROPERTY(int displayIntegerBase READ displayIntegerBase WRITE setDisplayIntegerBase) public: explicit QSpinBox(QWidget *parent = 0); @@ -87,6 +88,8 @@ public: void setRange(int min, int max); + int displayIntegerBase() const; + void setDisplayIntegerBase(int base); protected: bool event(QEvent *event); diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index a64b34c56a..004fdda5ef 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -98,6 +98,9 @@ private slots: void setValue_data(); void setValue(); + void setDisplayIntegerBase_data(); + void setDisplayIntegerBase(); + void setPrefixSuffix_data(); void setPrefixSuffix(); @@ -274,6 +277,61 @@ void tst_QSpinBox::setValue() QCOMPARE(spin.value(), expected); } +void tst_QSpinBox::setDisplayIntegerBase_data() +{ + QTest::addColumn("value"); + QTest::addColumn("base"); + QTest::addColumn("string"); + + QTest::newRow("base 10") << 42 << 10 << "42"; + QTest::newRow("base 2") << 42 << 2 << "101010"; + QTest::newRow("base 8") << 42 << 8 << "52"; + QTest::newRow("base 16") << 42 << 16 << "2a"; + QTest::newRow("base 0") << 42 << 0 << "42"; + QTest::newRow("base -4") << 42 << -4 << "42"; + QTest::newRow("base 40") << 42 << 40 << "42"; + + QTest::newRow("negative base 10") << -42 << 10 << "-42"; + QTest::newRow("negative base 2") << -42 << 2 << "-101010"; + QTest::newRow("negative base 8") << -42 << 8 << "-52"; + QTest::newRow("negative base 16") << -42 << 16 << "-2a"; + QTest::newRow("negative base 0") << -42 << 0 << "-42"; + QTest::newRow("negative base -4") << -42 << -4 << "-42"; + QTest::newRow("negative base 40") << -42 << 40 << "-42"; + + QTest::newRow("0 base 10") << 0 << 10 << "0"; + QTest::newRow("0 base 2") << 0 << 2 << "0"; + QTest::newRow("0 base 8") << 0 << 8 << "0"; + QTest::newRow("0 base 16") << 0 << 16 << "0"; + QTest::newRow("0 base 0") << 0 << 0 << "0"; + QTest::newRow("0 base -4") << 0 << -4 << "0"; + QTest::newRow("0 base 40") << 0 << 40 << "0"; +} + +void tst_QSpinBox::setDisplayIntegerBase() +{ + QFETCH(int, value); + QFETCH(int, base); + QFETCH(QString, string); + + SpinBox spin; + spin.setRange(INT_MIN, INT_MAX); + + spin.setValue(value); + QCOMPARE(spin.lineEdit()->text(), QString::number(value)); + + spin.setDisplayIntegerBase(base); + QCOMPARE(spin.lineEdit()->text(), string); + + spin.setValue(0); + QCOMPARE(spin.value(), 0); + QCOMPARE(spin.lineEdit()->text(), QString::number(0, base)); + + spin.lineEdit()->clear(); + QTest::keyClicks(spin.lineEdit(), string); + QCOMPARE(spin.value(), value); +} + void tst_QSpinBox::setPrefixSuffix_data() { QTest::addColumn("prefix");