diff --git a/examples/quick/quick-accessibility/content/Button.qml b/examples/quick/quick-accessibility/content/Button.qml index 96704de4fec5b43fbc6a285259d8948df8fbf976..2baa66f91a82be10668f96e363f2cdc452bb8128 100644 --- a/examples/quick/quick-accessibility/content/Button.qml +++ b/examples/quick/quick-accessibility/content/Button.qml @@ -42,7 +42,7 @@ Rectangle { Accessible.name: text Accessible.description: "This button does " + text Accessible.role: Accessible.Button - function accessiblePressAction() { + Accessible.onPressAction: { button.clicked() } //! [button] diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 3234d3d85f0a9f8afb6cdaaac5e60a5c28b3dbc7..e13224f6fbdb04ba5869a609e39be19684bb85cd 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -39,7 +39,6 @@ #include "QtQuick/private/qquicktext_p.h" #include "QtQuick/private/qquickaccessibleattached_p.h" #include "QtQuick/qquicktextdocument.h" - QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY @@ -217,16 +216,24 @@ QStringList QAccessibleQuickItem::actionNames() const QStringList actions = QQmlAccessible::actionNames(); if (state().focusable) actions.append(QAccessibleActionInterface::setFocusAction()); + + // ### The following can lead to duplicate action names. We'll fix that when we kill QQmlAccessible + if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item())) + attached->availableActions(&actions); return actions; } void QAccessibleQuickItem::doAction(const QString &actionName) { + bool accepted = false; if (actionName == QAccessibleActionInterface::setFocusAction()) { item()->forceActiveFocus(); - } else { - QQmlAccessible::doAction(actionName); + accepted = true; } + if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item())) + accepted = attached->doAction(actionName); + if (!accepted) + QQmlAccessible::doAction(actionName); } QStringList QAccessibleQuickItem::keyBindingsForAction(const QString &actionName) const diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index a4ab0a96b1f6fb72f86b0bf55efc16d1d6b803dd..38b26a53d0f041151b341d7ceeeb87e2e79c7c23 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE Accessible.role: Accessible.Button Accessible.name: label.text Accessible.description: "shows the next page" - function accessiblePressAction() { + Accessible.onPressAction: { // do a button click } } @@ -79,8 +79,8 @@ QT_BEGIN_NAMESPACE The name is a short and consise description of the control and should reflect the visual label. In this case it is not clear what the button does with the name only, so \l description contains an explanation. - There is also a function \c accessiblePressAction() which can be invoked by assistive tools to trigger - the button. This function needs to have the same effect as tapping or clicking the button would have. + There is also a signal handler \l {Accessible::pressAction}{Accessible.pressAction} which can be invoked by assistive tools to trigger + the button. This signal handler needs to have the same effect as tapping or clicking the button would have. \sa Accessibility */ @@ -117,7 +117,7 @@ QT_BEGIN_NAMESPACE \table \header \li \b {Role} - \li \b {Properties and functions} + \li \b {Properties and signals} \li \b {Explanation} \row \li All interactive elements @@ -128,13 +128,14 @@ QT_BEGIN_NAMESPACE can be moved from item to item. \row \li Button, CheckBox, RadioButton - \li \c accessiblePressAction() - \li A button should have a function with the name \c accessiblePressAction. - This function may be called by an assistive tool such as a screen-reader. + \li \l {Accessible::pressAction}{Accessible.pressAction} + \li A button should have a signal handler with the name \c onPressAction. + This signal may be emitted by an assistive tool such as a screen-reader. The implementation needs to behave the same as a mouse click or tap on the button. \row \li CheckBox, RadioButton - \li \l checkable, \l checked + \li \l checkable, \l checked, \l {Accessible::toggleAction}{Accessible.toggleAction} + \li The check state of the check box. Updated on Press, Check and Uncheck actions. \row \li Slider, SpinBox, Dial, ScrollBar @@ -142,7 +143,7 @@ QT_BEGIN_NAMESPACE \li These properties reflect the state and possible values for the elements. \row \li Slider, SpinBox, Dial, ScrollBar - \li \c accessibleIncreaseAction(), \c accessibleDecreaseAction() + \li \l {Accessible::increaseAction}{Accessible.increaseAction}, \l {Accessible::decreaseAction}{Accessible.decreaseAction} \li Actions to increase and decrease the value of the element. \endtable */ @@ -262,6 +263,40 @@ QT_BEGIN_NAMESPACE By default this property is \c false. */ +/*! + \qmlsignal QtQuick::Accessible::pressAction() + + This signal is emitted when a press action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onPressAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::toggleAction() + + This signal is emitted when a toggle action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onToggleAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::increaseAction() + + This signal is emitted when a increase action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onIncreaseAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::decreaseAction() + + This signal is emitted when a decrease action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onDecreaseAction. +*/ + +const QMetaMethod QQuickAccessibleAttached::sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction); +const QMetaMethod QQuickAccessibleAttached::sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction); +const QMetaMethod QQuickAccessibleAttached::sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction); +const QMetaMethod QQuickAccessibleAttached::sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction); + QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) : QObject(parent), m_role(QAccessible::NoRole) { @@ -306,6 +341,35 @@ void QQuickAccessibleAttached::setIgnored(bool ignored) } } +bool QQuickAccessibleAttached::doAction(const QString &actionName) +{ + const QMetaMethod *sig = 0; + if (actionName == QAccessibleActionInterface::pressAction()) + sig = &sigPress; + else if (actionName == QAccessibleActionInterface::toggleAction()) + sig = &sigToggle; + else if (actionName == QAccessibleActionInterface::increaseAction()) + sig = &sigIncrease; + else if (actionName == QAccessibleActionInterface::decreaseAction()) + sig = &sigDecrease; + + if (sig && isSignalConnected(*sig)) + return sig->invoke(this); + return false; +} + +void QQuickAccessibleAttached::availableActions(QStringList *actions) const +{ + if (isSignalConnected(sigPress)) + actions->append(QAccessibleActionInterface::pressAction()); + if (isSignalConnected(sigToggle)) + actions->append(QAccessibleActionInterface::toggleAction()); + if (isSignalConnected(sigIncrease)) + actions->append(QAccessibleActionInterface::increaseAction()); + if (isSignalConnected(sigDecrease)) + actions->append(QAccessibleActionInterface::decreaseAction()); +} + QT_END_NAMESPACE #endif diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 4875b2765a53acaccd90862c286135dd35e2fd05..53b1d2954de615eff1d46dc10b73a7a568d30845 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -188,6 +188,8 @@ public: QAccessible::State state() { return m_state; } bool ignored() const; + bool doAction(const QString &actionName); + void availableActions(QStringList *actions) const; public Q_SLOTS: void valueChanged() { @@ -206,6 +208,10 @@ Q_SIGNALS: void nameChanged(); void descriptionChanged(); void ignoredChanged(); + void pressAction(); + void toggleAction(); + void increaseAction(); + void decreaseAction(); private: QQuickItem *item() const { return static_cast<QQuickItem*>(parent()); } @@ -215,6 +221,11 @@ private: QString m_name; QString m_description; + static const QMetaMethod sigPress; + static const QMetaMethod sigToggle; + static const QMetaMethod sigIncrease; + static const QMetaMethod sigDecrease; + public: using QObject::property; }; diff --git a/tests/manual/accessibility/textandbuttons.qml b/tests/manual/accessibility/textandbuttons.qml index 48ce6e26e9f87cd12e1c391bc4dff6b660dadf24..74c3bf3897ce4f8717293aa51e94d1eeadeb38ef 100644 --- a/tests/manual/accessibility/textandbuttons.qml +++ b/tests/manual/accessibility/textandbuttons.qml @@ -50,9 +50,8 @@ Rectangle { Accessible.role : Accessible.Button - function accessibleAction(action) { - if (action == Qt.Press) - buttonAction() + Accessible.onPressAction: { + buttonAction() } function buttonAction() {