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 Pick-to: 6.8 Change-Id: I257ea44ed988c70cb4fc0cfc81c3b366c0a431eb Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
8ec25c9d6b
commit
34b5e43e62
@ -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