QDoubleValidator: don't assume the locale's exponent separator is 'e'

Some locales even have multi-character exponent separators. Scan the
actual locale-appropriate separator to determine whether it contains
any cased characters; if upper, prefer 'E' format, of lower prefer
'e'; but match the case of the input string in any case, when it has
case. Use 'e' when it has no case.

This doesn't currently change any test data, due to the bug that
QLocale::toString(double, 'e',...) uses the locale-appropriate case,
even if that is upper-case, contrary to its own docs. However, fixing
that bug breaks some of the tests of QDoubleValidator without this fix
to prepare for it.

Pick-to: 6.9 6.8 6.5
Task-number: QTBUG-134768
Change-Id: I0ba5bbdb507b8b6efdf6dc134c387fd3b4bcbeb2
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2025-03-19 11:03:03 +01:00
parent 2edb569773
commit 8c88a077cc

View File

@ -9,6 +9,7 @@
#include "private/qobject_p.h"
#include "private/qlocale_p.h"
#include "private/qnumeric_p.h"
#include "private/qstringiterator_p.h"
#include <limits.h>
#include <cmath>
@ -757,8 +758,19 @@ void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::Numbe
if (numMode == QLocaleData::DoubleStandardMode) {
mode = 'f';
} else {
// scientific mode can be either 'e' or 'E'
mode = input.contains(QChar::fromLatin1('E')) ? 'E' : 'e';
// Scientific mode can be either 'e' or 'E'
const QString exp = locale.exponential();
bool preferUpper = false;
QStringIterator scan(exp);
while (!preferUpper && scan.hasNext()) {
const char32_t ch = scan.next();
if (QChar::isUpper(ch))
preferUpper = true;
}
if (preferUpper)
mode = input.contains(exp.toLower()) ? 'e' : 'E';
else // If case-free, we don't care which we use; otherwise, prefer lower.
mode = input.contains(exp.toUpper()) ? 'E' : 'e';
}
int precision;
if (q->dec < 0) {