summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2022-02-10 16:43:38 +0100
committerIvan Solovev <ivan.solovev@qt.io>2022-02-15 17:51:33 +0100
commit60799fc14134472913af4b3ab87b6160bd46056d (patch)
treeb67d0e4bc9a60913883602ba0eb60c8f35565575 /src/plugins/platforms/android
parenta374d59abc415eee1866322176b7762158f48abd (diff)
Android A11Y: Fix value rounding
QAccessibleInterface stores values as QVariants. When dealing with double values, as a result of some calculation (for example, Slider value update), rounding errors can be introduced. When converting double values to QString using QVariant::toString(), these rounding errors result in strings like 0.30000000000000004 instead of 0.3 or 2.7755575615628914e-17 instead of 0.3 - 3 * 0.1 and similar zeroes. To fix this issue, this patch introduces a custom conversion for floating-point values. The idea is to convert QVariant to double, and then convert double to QString using 'f' format and a suitable precision, determined from the UI element's minimumStepSize(), if it has one, otherwise falling back to QString::number()'s default (which is 6). Task-number: QTBUG-93396 Pick-to: 6.3 6.2 5.15 Change-Id: Ia5ca7345812e39629e9c191b6d8b896a8f51de80 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index cac106be3b..807db78ecf 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -358,8 +358,50 @@ if (!clazz) { \
QString valueStr;
QAccessibleValueInterface *valueIface = iface->valueInterface();
if (valueIface) {
- // TODO: fix double-to-string conversion
- valueStr = valueIface->currentValue().toString();
+ const QVariant valueVar = valueIface->currentValue();
+ const auto type = valueVar.typeId();
+ if (type == QMetaType::Double || type == QMetaType::Float) {
+ // QVariant's toString() formats floating-point values with
+ // FloatingPointShortest, which is not an accessible
+ // representation; nor, in many cases, is it suitable to the UI
+ // element whose value we're looking at. So roll our own
+ // A11Y-friendly conversion to string.
+ const double val = valueVar.toDouble();
+ // Try to use minimumStepSize() to determine precision
+ bool stepIsValid = false;
+ const double step = qAbs(valueIface->minimumStepSize().toDouble(&stepIsValid));
+ if (!stepIsValid || qFuzzyIsNull(step)) {
+ // Ignore step, use default precision
+ valueStr = qFuzzyIsNull(val) ? u"0"_qs : QString::number(val, 'f');
+ } else {
+ const int precision = [](double s) {
+ int count = 0;
+ while (s < 1. && !qFuzzyCompare(s, 1.)) {
+ ++count;
+ s *= 10;
+ }
+ // If s is now 1.25, we want to show some more digits,
+ // but don't want to get silly with a step like 1./7;
+ // so only include a few extra digits.
+ const int stop = count + 3;
+ const auto fractional = [](double v) {
+ double whole = 0.0;
+ std::modf(v + 0.5, &whole);
+ return qAbs(v - whole);
+ };
+ s = fractional(s);
+ while (count < stop && !qFuzzyIsNull(s)) {
+ ++count;
+ s = fractional(s * 10);
+ }
+ return count;
+ }(step);
+ valueStr = qFuzzyIsNull(val / step) ? u"0"_qs
+ : QString::number(val, 'f', precision);
+ }
+ } else {
+ valueStr = valueVar.toString();
+ }
}
return valueStr;
}