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:
Morteza Jamshidi 2024-10-30 12:34:30 +01:00 committed by Qt Cherry-pick Bot
parent d8ed810029
commit d610103126
2 changed files with 85 additions and 9 deletions

View File

@ -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);
}
/*!

View File

@ -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"