| 1 | // Copyright (C) 2016 The Qt Company Ltd. |
|---|---|
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | #include "qaccessiblebridgeutils_p.h" |
| 4 | #include <QtCore/qmath.h> |
| 5 | |
| 6 | QT_BEGIN_NAMESPACE |
| 7 | |
| 8 | namespace QAccessibleBridgeUtils { |
| 9 | |
| 10 | static bool performAction(QAccessibleInterface *iface, const QString &actionName) |
| 11 | { |
| 12 | if (QAccessibleActionInterface *actionIface = iface->actionInterface()) { |
| 13 | if (actionIface->actionNames().contains(str: actionName)) { |
| 14 | actionIface->doAction(actionName); |
| 15 | return true; |
| 16 | } |
| 17 | } |
| 18 | return false; |
| 19 | } |
| 20 | |
| 21 | QStringList effectiveActionNames(QAccessibleInterface *iface) |
| 22 | { |
| 23 | QStringList actions; |
| 24 | if (QAccessibleActionInterface *actionIface = iface->actionInterface()) |
| 25 | actions = actionIface->actionNames(); |
| 26 | |
| 27 | if (iface->valueInterface()) { |
| 28 | if (!actions.contains(str: QAccessibleActionInterface::increaseAction())) |
| 29 | actions << QAccessibleActionInterface::increaseAction(); |
| 30 | if (!actions.contains(str: QAccessibleActionInterface::decreaseAction())) |
| 31 | actions << QAccessibleActionInterface::decreaseAction(); |
| 32 | } |
| 33 | return actions; |
| 34 | } |
| 35 | |
| 36 | bool performEffectiveAction(QAccessibleInterface *iface, const QString &actionName) |
| 37 | { |
| 38 | if (!iface) |
| 39 | return false; |
| 40 | if (performAction(iface, actionName)) |
| 41 | return true; |
| 42 | if (actionName != QAccessibleActionInterface::increaseAction() |
| 43 | && actionName != QAccessibleActionInterface::decreaseAction()) |
| 44 | return false; |
| 45 | |
| 46 | QAccessibleValueInterface *valueIface = iface->valueInterface(); |
| 47 | if (!valueIface) |
| 48 | return false; |
| 49 | bool success; |
| 50 | const QVariant currentVariant = valueIface->currentValue(); |
| 51 | double stepSize = valueIface->minimumStepSize().toDouble(ok: &success); |
| 52 | if (!success || qFuzzyIsNull(d: stepSize)) { |
| 53 | const double min = valueIface->minimumValue().toDouble(ok: &success); |
| 54 | if (!success) |
| 55 | return false; |
| 56 | const double max = valueIface->maximumValue().toDouble(ok: &success); |
| 57 | if (!success) |
| 58 | return false; |
| 59 | stepSize = (max - min) / 10; // this is pretty arbitrary, we just need to provide something |
| 60 | const int typ = currentVariant.userType(); |
| 61 | if (typ != QMetaType::Float && typ != QMetaType::Double) { |
| 62 | // currentValue is an integer. Round it up to ensure stepping in case it was below 1 |
| 63 | stepSize = qCeil(v: stepSize); |
| 64 | } |
| 65 | } |
| 66 | const double current = currentVariant.toDouble(ok: &success); |
| 67 | if (!success) |
| 68 | return false; |
| 69 | if (actionName == QAccessibleActionInterface::decreaseAction()) |
| 70 | stepSize = -stepSize; |
| 71 | valueIface->setCurrentValue(current + stepSize); |
| 72 | return true; |
| 73 | } |
| 74 | |
| 75 | QString accessibleId(QAccessibleInterface *accessible) { |
| 76 | QString result; |
| 77 | if (!accessible) |
| 78 | return result; |
| 79 | result = accessible->text(t: QAccessible::Identifier); |
| 80 | if (!result.isEmpty()) |
| 81 | return result; |
| 82 | while (accessible) { |
| 83 | if (!result.isEmpty()) |
| 84 | result.prepend(c: u'.'); |
| 85 | if (auto obj = accessible->object()) { |
| 86 | const QString name = obj->objectName(); |
| 87 | if (!name.isEmpty()) |
| 88 | result.prepend(s: name); |
| 89 | else |
| 90 | result.prepend(s: QString::fromUtf8(utf8: obj->metaObject()->className())); |
| 91 | } |
| 92 | accessible = accessible->parent(); |
| 93 | } |
| 94 | return result; |
| 95 | } |
| 96 | |
| 97 | } //namespace |
| 98 | |
| 99 | QT_END_NAMESPACE |
| 100 |
