From f28755240b9d72eb748c2f9469a58601bffdecf1 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 25 Sep 2014 11:41:44 +0200 Subject: Support Accessible.ignored on non-leaf items Ignoring items with children will make the children appear as children of the parent of the ignored item. Since setAccessibleFlagAndListener now only sets the flag we also rename the function to just setAccessible Change-Id: I79fc311509a3e454b4698274c63ad0e879fb93e3 Reviewed-by: Frederik Gladhorn --- src/quick/accessible/qaccessiblequickitem.cpp | 21 +++- src/quick/accessible/qaccessiblequickitem_p.h | 1 - src/quick/items/qquickaccessibleattached.cpp | 2 +- src/quick/items/qquickitem.cpp | 15 +-- src/quick/items/qquickitem_p.h | 2 +- tests/auto/quick/qquickaccessible/data/hittest.qml | 1 + tests/auto/quick/qquickaccessible/data/ignored.qml | 127 +++++++++++++++++++++ .../quick/qquickaccessible/qquickaccessible.pro | 9 +- .../qquickaccessible/tst_qquickaccessible.cpp | 33 ++++++ 9 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 tests/auto/quick/qquickaccessible/data/ignored.qml diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index fe01326bbc..3f023ae621 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -108,7 +108,7 @@ QAccessibleInterface *QAccessibleQuickItem::parent() const QQuickItem *parent = item()->parentItem(); QQuickWindow *window = item()->window(); QQuickItem *ci = window ? window->contentItem() : 0; - while (parent && parent != ci) + while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) parent = parent->parentItem(); if (parent) { @@ -120,6 +120,8 @@ QAccessibleInterface *QAccessibleQuickItem::parent() const // it here and return an interface for the scene instead. return QAccessible::queryAccessibleInterface(window); } else { + while (parent && !parent->d_func()->isAccessible) + parent = parent->parentItem(); return QAccessible::queryAccessibleInterface(parent); } } @@ -146,16 +148,23 @@ int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const return kids.indexOf(static_cast(iface->object())); } -QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +static void unignoredChildren(QQuickItem *item, QList *items, bool paintOrder) { - QList items; QList childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems() : item->childItems(); Q_FOREACH (QQuickItem *child, childItems) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); - if (itemPrivate->isAccessible) - items.append(child); + if (QQuickItemPrivate::get(child)->isAccessible) { + items->append(child); + } else { + unignoredChildren(child, items, paintOrder); + } } +} + +QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +{ + QList items; + unignoredChildren(item, &items, paintOrder); return items; } diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h index 84e82fff86..e8486721f3 100644 --- a/src/quick/accessible/qaccessiblequickitem_p.h +++ b/src/quick/accessible/qaccessiblequickitem_p.h @@ -121,7 +121,6 @@ private: QRect itemScreenRect(QQuickItem *item); QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder = false); - #endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 3f0ebab6f3..59c0c2e8a0 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -266,7 +266,7 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) // Enable accessibility for items with accessible content. This also // enables accessibility for the ancestors of souch items. - item->d_func()->setAccessibleFlagAndListener(); + item->d_func()->setAccessible(); QAccessibleEvent ev(item, QAccessible::ObjectCreated); QAccessible::updateAccessibility(&ev); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ebe136e556..a1376682af 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1607,17 +1607,9 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) } } -void QQuickItemPrivate::setAccessibleFlagAndListener() +void QQuickItemPrivate::setAccessible() { - Q_Q(QQuickItem); - QQuickItem *item = q; - while (item) { - if (item->d_func()->isAccessible) - break; // already set - grandparents should have the flag set as well. - - item->d_func()->isAccessible = true; - item = item->d_func()->parentItem; - } + isAccessible = true; } /*! @@ -2584,9 +2576,6 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) d->itemChange(ItemParentHasChanged, d->parentItem); d->parentNotifier.notify(); - if (d->isAccessible && d->parentItem) { - d->parentItem->d_func()->setAccessibleFlagAndListener(); - } emit parentChanged(d->parentItem); if (isVisible() && d->parentItem) diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 4b54dc44af..7ef0f903b5 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -510,7 +510,7 @@ public: inline qreal rotation() const { return extra.isAllocated()?extra->rotation:0; } inline qreal opacity() const { return extra.isAllocated()?extra->opacity:1; } - void setAccessibleFlagAndListener(); + void setAccessible(); virtual qreal getImplicitWidth() const; virtual qreal getImplicitHeight() const; diff --git a/tests/auto/quick/qquickaccessible/data/hittest.qml b/tests/auto/quick/qquickaccessible/data/hittest.qml index 97eb6013a1..f081f5476e 100644 --- a/tests/auto/quick/qquickaccessible/data/hittest.qml +++ b/tests/auto/quick/qquickaccessible/data/hittest.qml @@ -41,6 +41,7 @@ Rectangle { height: 480 color: "white" Accessible.name: "root" + Accessible.role: Accessible.Client Rectangle { id: header color: "#c0c0c0" diff --git a/tests/auto/quick/qquickaccessible/data/ignored.qml b/tests/auto/quick/qquickaccessible/data/ignored.qml new file mode 100644 index 0000000000..1caf6ccb56 --- /dev/null +++ b/tests/auto/quick/qquickaccessible/data/ignored.qml @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +import QtQuick 2.0 +import "widgets" + + +Rectangle { + id: page + width: 640 + height: 480 + function col(str) { + return Qt.hsla((str.charCodeAt(0)-65)/9, 1.0, 0.5, 1) + } + color: col(Accessible.name) + Accessible.name: "A" + Accessible.role: Accessible.StaticText + + Rectangle { + id: b + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "B" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 20 + width: 80 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.ignored: true + Accessible.name: "C" + Accessible.role: Accessible.StaticText + + Rectangle { + width: 20 + color: col(Accessible.name) + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + Accessible.name: "E" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 20 + width: 20 + color: col(Accessible.name) + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + Accessible.name: "F" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 40 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.ignored: true + Accessible.name: "G" + Accessible.role: Accessible.StaticText + Rectangle { + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "I" + Accessible.role: Accessible.StaticText + } + } + Rectangle { + x: 60 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "H" + Accessible.role: Accessible.StaticText + } + } + + Rectangle { + x: 100 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "D" + Accessible.role: Accessible.StaticText + } +} diff --git a/tests/auto/quick/qquickaccessible/qquickaccessible.pro b/tests/auto/quick/qquickaccessible/qquickaccessible.pro index 99c3834147..bdbe2e3fb4 100644 --- a/tests/auto/quick/qquickaccessible/qquickaccessible.pro +++ b/tests/auto/quick/qquickaccessible/qquickaccessible.pro @@ -10,10 +10,11 @@ include (../../shared/util.pri) TESTDATA = data/* -OTHER_FILES += data/checkbuttons.qml -OTHER_FILES += data/hittest.qml -OTHER_FILES += data/pushbutton.qml -OTHER_FILES += data/statictext.qml +OTHER_FILES += data/checkbuttons.qml \ + data/hittest.qml \ + data/pushbutton.qml \ + data/statictext.qml \ + data/ignored.qml \ CONFIG += parallel_test diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp index c514f96d24..921c81ae89 100644 --- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp +++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp @@ -106,6 +106,7 @@ private slots: void basicPropertiesTest(); void hitTest(); void checkableTest(); + void ignoredTest(); }; tst_QQuickAccessible::tst_QQuickAccessible() @@ -456,6 +457,38 @@ void tst_QQuickAccessible::checkableTest() QTestAccessibility::clearEvents(); } +void tst_QQuickAccessible::ignoredTest() +{ + QScopedPointer window(new QQuickView()); + window->setSource(testFileUrl("ignored.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QQuickItem *contentItem = window->contentItem(); + QVERIFY(contentItem); + QQuickItem *rootItem = contentItem->childItems().first(); + QVERIFY(rootItem); + + // the window becomes active + QAccessible::State activatedChange; + activatedChange.active = true; + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data()); + QVERIFY(iface); + QAccessibleInterface *rectangleA = iface->child(0); + + QCOMPARE(rectangleA->role(), QAccessible::StaticText); + QCOMPARE(rectangleA->text(QAccessible::Name), QLatin1String("A")); + static const char *expected = "BEFIHD"; + // check if node "C" and "G" is skipped and that the order is as expected. + for (int i = 0; i < rectangleA->childCount(); ++i) { + QAccessibleInterface *child = rectangleA->child(i); + QCOMPARE(child->text(QAccessible::Name), QString(QLatin1Char(expected[i]))); + } + QTestAccessibility::clearEvents(); +} + QTEST_MAIN(tst_QQuickAccessible) #include "tst_qquickaccessible.moc" -- cgit v1.2.3