QDoubleSpinBox: Use QLocale to omit group separators
Instead of removing group separators after conversion, we can omit them using QLocale. The decimal point and group separators can be the same character, if the user configures the system locale accordingly. Add a test that compares the text shown by the spinbox with what the locale would do. Since the C locale sets the OmitGroupSeperator number option by default, cover several cases to verify that we explicitly set the correct number options based on the QDoubleSpinBox property, and implement a customized system locale that returns the same character for group separator and decimal point. Fixes: QTBUG-77939 Change-Id: I257ea44ed988c70cb4fc0cfc81c3b366c0a431eb Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 34b5e43e6259c6362c642a244ceb26d482f35b82) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d8ed810029
commit
d610103126
@ -484,10 +484,12 @@ QString QSpinBox::textFromValue(int value) const
|
||||
const auto prefix = value < 0 ? "-"_L1 : ""_L1;
|
||||
str = prefix + QString::number(qAbs(value), d->displayIntegerBase);
|
||||
} else {
|
||||
str = locale().toString(value);
|
||||
if (!d->showGroupSeparator && (qAbs(value) >= 1000 || value == INT_MIN)) {
|
||||
str.remove(locale().groupSeparator());
|
||||
}
|
||||
QLocale loc = locale();
|
||||
if (d->showGroupSeparator)
|
||||
loc.setNumberOptions(loc.numberOptions() & ~QLocale::OmitGroupSeparator);
|
||||
else
|
||||
loc.setNumberOptions(loc.numberOptions() | QLocale::OmitGroupSeparator);
|
||||
str = loc.toString(value);
|
||||
}
|
||||
|
||||
return str;
|
||||
@ -959,11 +961,12 @@ void QDoubleSpinBox::setDecimals(int decimals)
|
||||
QString QDoubleSpinBox::textFromValue(double value) const
|
||||
{
|
||||
Q_D(const QDoubleSpinBox);
|
||||
QString str = locale().toString(value, 'f', d->decimals);
|
||||
if (!d->showGroupSeparator && qAbs(value) >= 1000.0)
|
||||
str.remove(locale().groupSeparator());
|
||||
|
||||
return str;
|
||||
QLocale loc = locale();
|
||||
if (d->showGroupSeparator)
|
||||
loc.setNumberOptions(loc.numberOptions() & ~QLocale::OmitGroupSeparator);
|
||||
else
|
||||
loc.setNumberOptions(loc.numberOptions() | QLocale::OmitGroupSeparator);
|
||||
return loc.toString(value, 'f', d->decimals);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <QtWidgets/private/qapplication_p.h>
|
||||
|
||||
#include <QtCore/private/qlocale_p.h> // for QSystemLocale
|
||||
|
||||
class DoubleSpinBox : public QDoubleSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -184,6 +186,10 @@ private slots:
|
||||
|
||||
void stepModifierPressAndHold_data();
|
||||
void stepModifierPressAndHold();
|
||||
|
||||
void digitGroupingControl_data();
|
||||
void digitGroupingControl();
|
||||
|
||||
public slots:
|
||||
void valueChangedHelper(const QString &);
|
||||
void valueChangedHelper(double);
|
||||
@ -1767,5 +1773,72 @@ void tst_QDoubleSpinBox::stepModifierPressAndHold()
|
||||
QCOMPARE(value.toDouble(), spy.size() * expectedStepModifier);
|
||||
}
|
||||
|
||||
void tst_QDoubleSpinBox::digitGroupingControl_data()
|
||||
{
|
||||
QTest::addColumn<QLocale>("locale");
|
||||
|
||||
QTest::addRow("en_US") << QLocale("en_US");
|
||||
QTest::addRow("C") << QLocale("C");
|
||||
#if !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||
QTest::addRow("system") << QLocale(QLocale::AnyLanguage);
|
||||
#endif // !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||
}
|
||||
|
||||
void tst_QDoubleSpinBox::digitGroupingControl()
|
||||
{
|
||||
QFETCH(QLocale, locale);
|
||||
|
||||
#if !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||
class MySystemLocale : public QSystemLocale
|
||||
{
|
||||
Q_DISABLE_COPY_MOVE(MySystemLocale)
|
||||
public:
|
||||
MySystemLocale(const QLocale &fallback)
|
||||
: m_fallback(fallback)
|
||||
{}
|
||||
|
||||
QVariant query(QueryType type, QVariant &&/*in*/) const override
|
||||
{
|
||||
switch (type) {
|
||||
case GroupSeparator:
|
||||
case DecimalPoint:
|
||||
return QVariant(".");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QLocale fallbackLocale() const override { return m_fallback; }
|
||||
|
||||
private:
|
||||
const QLocale m_fallback;
|
||||
} customLocale(locale);
|
||||
|
||||
if (locale.language() == QLocale::AnyLanguage) {
|
||||
// For the lifetime of `customLocale`, the system locale will use our
|
||||
// custom implementation above.
|
||||
locale = QLocale::system();
|
||||
}
|
||||
#endif // !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||
|
||||
QDoubleSpinBox spinbox;
|
||||
spinbox.setLocale(locale);
|
||||
spinbox.setRange(-100000, 100000);
|
||||
|
||||
constexpr int precision = 3;
|
||||
constexpr double value = 12345.678;
|
||||
spinbox.setDecimals(precision);
|
||||
spinbox.setValue(value);
|
||||
|
||||
spinbox.setGroupSeparatorShown(true);
|
||||
locale.setNumberOptions(locale.numberOptions() & ~QLocale::OmitGroupSeparator);
|
||||
QCOMPARE(spinbox.text(), locale.toString(value, 'f', precision));
|
||||
|
||||
spinbox.setGroupSeparatorShown(false);
|
||||
locale.setNumberOptions(locale.numberOptions() | QLocale::OmitGroupSeparator);
|
||||
QCOMPARE(spinbox.text(), locale.toString(value, 'f', precision));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDoubleSpinBox)
|
||||
#include "tst_qdoublespinbox.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user