411 lines
13 KiB
C++
411 lines
13 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/
|
|
**
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** GNU Lesser General Public License Usage
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU Lesser
|
|
** General Public License version 2.1 requirements will be met:
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU General
|
|
** Public License version 3.0 as published by the Free Software Foundation
|
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU General
|
|
** Public License version 3.0 requirements will be met:
|
|
** http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** Other Usage
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
#include "QtTest/qtestaccessible.h"
|
|
|
|
#include <QtGui/qaccessible.h>
|
|
|
|
#include <QtQuick/qquickview.h>
|
|
#include <QtQuick/qquickitem.h>
|
|
|
|
#include <QtQml/qqmlengine.h>
|
|
#include <QtQml/qqmlproperty.h>
|
|
#include <QtQuick/private/qquickaccessibleattached_p.h>
|
|
|
|
#include "../../shared/util.h"
|
|
|
|
|
|
typedef QSharedPointer<QAccessibleInterface> QAI;
|
|
|
|
#define EXPECT(cond) \
|
|
do { \
|
|
if (!errorAt && !(cond)) { \
|
|
errorAt = __LINE__; \
|
|
qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
|
|
} \
|
|
} while (0)
|
|
|
|
static int verifyHierarchy(QAccessibleInterface *iface)
|
|
{
|
|
int errorAt = 0;
|
|
static int treelevel = 0; // for error diagnostics
|
|
QAccessibleInterface *middleChild, *if2;
|
|
middleChild = 0;
|
|
++treelevel;
|
|
int middle = iface->childCount()/2 + 1;
|
|
if (iface->childCount() >= 2) {
|
|
middleChild = iface->child(middle - 1);
|
|
}
|
|
for (int i = 0; i < iface->childCount() && !errorAt; ++i) {
|
|
if2 = iface->child(i);
|
|
EXPECT(if2 != 0);
|
|
// navigate Ancestor...
|
|
QAccessibleInterface *parent = if2->parent();
|
|
EXPECT(iface->object() == parent->object());
|
|
delete parent;
|
|
|
|
// verify children...
|
|
if (!errorAt)
|
|
errorAt = verifyHierarchy(if2);
|
|
delete if2;
|
|
}
|
|
delete middleChild;
|
|
|
|
--treelevel;
|
|
return errorAt;
|
|
}
|
|
|
|
|
|
//TESTED_FILES=
|
|
|
|
class tst_QQuickAccessible : public QQmlDataTest
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
tst_QQuickAccessible();
|
|
virtual ~tst_QQuickAccessible();
|
|
|
|
private slots:
|
|
void commonTests_data();
|
|
void commonTests();
|
|
|
|
void quickAttachedProperties();
|
|
void basicPropertiesTest();
|
|
void hitTest();
|
|
void checkableTest();
|
|
};
|
|
|
|
tst_QQuickAccessible::tst_QQuickAccessible()
|
|
{
|
|
|
|
}
|
|
|
|
tst_QQuickAccessible::~tst_QQuickAccessible()
|
|
{
|
|
|
|
}
|
|
|
|
void tst_QQuickAccessible::commonTests_data()
|
|
{
|
|
QTest::addColumn<QString>("accessibleRoleFileName");
|
|
|
|
QTest::newRow("StaticText") << "statictext.qml";
|
|
QTest::newRow("PushButton") << "pushbutton.qml";
|
|
}
|
|
|
|
void tst_QQuickAccessible::commonTests()
|
|
{
|
|
QFETCH(QString, accessibleRoleFileName);
|
|
|
|
qDebug() << "testing" << accessibleRoleFileName;
|
|
|
|
QQuickView *view = new QQuickView();
|
|
// view->setFixedSize(240,320);
|
|
view->setSource(testFileUrl(accessibleRoleFileName));
|
|
view->show();
|
|
// view->setFocus();
|
|
QVERIFY(view->rootObject() != 0);
|
|
|
|
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(view);
|
|
QVERIFY(iface);
|
|
|
|
delete iface;
|
|
delete view;
|
|
}
|
|
|
|
|
|
|
|
QString eventName(const int ev)
|
|
{
|
|
switch (ev) {
|
|
case 0x0001: return "SoundPlayed";
|
|
case 0x0002: return "Alert";
|
|
case 0x0003: return "ForegroundChanged";
|
|
case 0x0004: return "MenuStart";
|
|
case 0x0005: return "MenuEnd";
|
|
case 0x0006: return "PopupMenuStart";
|
|
case 0x0007: return "PopupMenuEnd";
|
|
case 0x000C: return "ContextHelpStart";
|
|
case 0x000D: return "ContextHelpEnd";
|
|
case 0x000E: return "DragDropStart";
|
|
case 0x000F: return "DragDropEnd";
|
|
case 0x0010: return "DialogStart";
|
|
case 0x0011: return "DialogEnd";
|
|
case 0x0012: return "ScrollingStart";
|
|
case 0x0013: return "ScrollingEnd";
|
|
case 0x0018: return "MenuCommand";
|
|
case 0x8000: return "ObjectCreated";
|
|
case 0x8001: return "ObjectDestroyed";
|
|
case 0x8002: return "ObjectShow";
|
|
case 0x8003: return "ObjectHide";
|
|
case 0x8004: return "ObjectReorder";
|
|
case 0x8005: return "Focus";
|
|
case 0x8006: return "Selection";
|
|
case 0x8007: return "SelectionAdd";
|
|
case 0x8008: return "SelectionRemove";
|
|
case 0x8009: return "SelectionWithin";
|
|
case 0x800A: return "StateChanged";
|
|
case 0x800B: return "LocationChanged";
|
|
case 0x800C: return "NameChanged";
|
|
case 0x800D: return "DescriptionChanged";
|
|
case 0x800E: return "ValueChanged";
|
|
case 0x800F: return "ParentChanged";
|
|
case 0x80A0: return "HelpChanged";
|
|
case 0x80B0: return "DefaultActionChanged";
|
|
case 0x80C0: return "AcceleratorChanged";
|
|
default: return "Unknown Event";
|
|
}
|
|
}
|
|
|
|
void tst_QQuickAccessible::quickAttachedProperties()
|
|
{
|
|
{
|
|
QQmlEngine engine;
|
|
QQmlComponent component(&engine);
|
|
component.setData("import QtQuick 2.0\nItem {\n"
|
|
"}", QUrl());
|
|
QObject *object = component.create();
|
|
QVERIFY(object != 0);
|
|
|
|
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
|
|
QCOMPARE(attachedObject, static_cast<QObject*>(0));
|
|
delete object;
|
|
}
|
|
|
|
// Attached property
|
|
{
|
|
QObject parent;
|
|
QQuickAccessibleAttached *attachedObj = new QQuickAccessibleAttached(&parent);
|
|
|
|
attachedObj->name();
|
|
|
|
QVariant pp = attachedObj->property("name");
|
|
QQmlEngine engine;
|
|
QQmlComponent component(&engine);
|
|
component.setData("import QtQuick 2.0\nItem {\n"
|
|
"Accessible.role: Accessible.Button\n"
|
|
"}", QUrl());
|
|
QObject *object = component.create();
|
|
QVERIFY(object != 0);
|
|
|
|
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
|
|
QVERIFY(attachedObject);
|
|
if (attachedObject) {
|
|
QVariant p = attachedObject->property("role");
|
|
QCOMPARE(p.isNull(), false);
|
|
QCOMPARE(p.toInt(), int(QAccessible::PushButton));
|
|
p = attachedObject->property("name");
|
|
QCOMPARE(p.isNull(), true);
|
|
p = attachedObject->property("description");
|
|
QCOMPARE(p.isNull(), true);
|
|
}
|
|
delete object;
|
|
}
|
|
|
|
// Attached property
|
|
{
|
|
QQmlEngine engine;
|
|
QQmlComponent component(&engine);
|
|
component.setData("import QtQuick 2.0\nItem {\n"
|
|
"Accessible.role: Accessible.Button\n"
|
|
"Accessible.name: \"Donald\"\n"
|
|
"Accessible.description: \"Duck\"\n"
|
|
"}", QUrl());
|
|
QObject *object = component.create();
|
|
QVERIFY(object != 0);
|
|
|
|
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
|
|
QVERIFY(attachedObject);
|
|
if (attachedObject) {
|
|
QVariant p = attachedObject->property("role");
|
|
QCOMPARE(p.isNull(), false);
|
|
QCOMPARE(p.toInt(), int(QAccessible::PushButton));
|
|
p = attachedObject->property("name");
|
|
QCOMPARE(p.isNull(), false);
|
|
QCOMPARE(p.toString(), QLatin1String("Donald"));
|
|
p = attachedObject->property("description");
|
|
QCOMPARE(p.isNull(), false);
|
|
QCOMPARE(p.toString(), QLatin1String("Duck"));
|
|
}
|
|
delete object;
|
|
}
|
|
}
|
|
|
|
|
|
void tst_QQuickAccessible::basicPropertiesTest()
|
|
{
|
|
QAI app = QAI(QAccessible::queryAccessibleInterface(qApp));
|
|
QCOMPARE(app->childCount(), 0);
|
|
|
|
QQuickView *canvas = new QQuickView();
|
|
canvas->setSource(testFileUrl("statictext.qml"));
|
|
canvas->show();
|
|
QCOMPARE(app->childCount(), 1);
|
|
|
|
QAI iface = QAI(QAccessible::queryAccessibleInterface(canvas));
|
|
QVERIFY(iface.data());
|
|
QCOMPARE(iface->childCount(), 1);
|
|
|
|
QAI item = QAI(iface->child(0));
|
|
QVERIFY(item.data());
|
|
QCOMPARE(item->childCount(), 2);
|
|
QCOMPARE(item->rect().size(), QSize(400, 400));
|
|
QCOMPARE(item->role(), QAccessible::Pane);
|
|
QCOMPARE(iface->indexOfChild(item.data()), 0);
|
|
|
|
QAI text = QAI(item->child(0));
|
|
QVERIFY(text.data());
|
|
QCOMPARE(text->childCount(), 0);
|
|
|
|
QCOMPARE(text->text(QAccessible::Name), QLatin1String("Hello Accessibility"));
|
|
QCOMPARE(text->rect().size(), QSize(200, 50));
|
|
QCOMPARE(text->rect().x(), item->rect().x() + 100);
|
|
QCOMPARE(text->rect().y(), item->rect().y() + 20);
|
|
QCOMPARE(text->role(), QAccessible::StaticText);
|
|
QCOMPARE(item->indexOfChild(text.data()), 0);
|
|
|
|
QAI text2 = QAI(item->child(1));
|
|
QVERIFY(text2.data());
|
|
QCOMPARE(text2->childCount(), 0);
|
|
|
|
QCOMPARE(text2->text(QAccessible::Name), QLatin1String("The Hello 2 accessible text"));
|
|
QCOMPARE(text2->rect().size(), QSize(100, 40));
|
|
QCOMPARE(text2->rect().x(), item->rect().x() + 100);
|
|
QCOMPARE(text2->rect().y(), item->rect().y() + 40);
|
|
QCOMPARE(text2->role(), QAccessible::StaticText);
|
|
QCOMPARE(item->indexOfChild(text2.data()), 1);
|
|
|
|
QCOMPARE(iface->indexOfChild(text2.data()), -1);
|
|
QCOMPARE(text2->indexOfChild(item.data()), -1);
|
|
|
|
delete canvas;
|
|
}
|
|
|
|
QAI topLevelChildAt(QAccessibleInterface *iface, int x, int y)
|
|
{
|
|
QAI child = QAI(iface->childAt(x, y));
|
|
if (!child)
|
|
return QAI();
|
|
|
|
QAI childOfChild;
|
|
while (childOfChild = QAI(child->childAt(x, y))) {
|
|
child = childOfChild;
|
|
}
|
|
return child;
|
|
}
|
|
|
|
void tst_QQuickAccessible::hitTest()
|
|
{
|
|
QQuickView *canvas = new QQuickView;
|
|
canvas->setSource(testFileUrl("hittest.qml"));
|
|
canvas->show();
|
|
|
|
QAI iface = QAI(QAccessible::queryAccessibleInterface(canvas));
|
|
QVERIFY(iface.data());
|
|
QAI rootItem = QAI(iface->child(0));
|
|
QRect rootRect = rootItem->rect();
|
|
|
|
// hit the root item
|
|
QAI itemHit(iface->childAt(rootRect.x() + 200, rootRect.y() + 50));
|
|
QVERIFY(itemHit);
|
|
QCOMPARE(rootRect, itemHit->rect());
|
|
|
|
// hit rect1
|
|
QAI rect1(rootItem->child(1));
|
|
QRect rect1Rect = rect1->rect();
|
|
itemHit = QAI(rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10));
|
|
QVERIFY(itemHit);
|
|
QCOMPARE(rect1Rect, itemHit->rect());
|
|
QCOMPARE(itemHit->text(QAccessible::Name), QLatin1String("rect1"));
|
|
|
|
// should also work from top level (app)
|
|
QAI app(QAccessible::queryAccessibleInterface(qApp));
|
|
QAI itemHit2(topLevelChildAt(app.data(), rect1Rect.x() + 10, rect1Rect.y() + 10));
|
|
QVERIFY(itemHit2);
|
|
QCOMPARE(itemHit2->rect(), rect1Rect);
|
|
QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1"));
|
|
|
|
// hit rect201
|
|
QAI rect2(rootItem->child(2));
|
|
QAI rect20(rect2->child(1));
|
|
QAI rect201(rect20->child(2));
|
|
QVERIFY(rect201);
|
|
|
|
QRect rect201Rect = rect201->rect();
|
|
itemHit = QAI(iface->childAt(rect201Rect.x() + 20, rect201Rect.y() + 20));
|
|
QVERIFY(itemHit);
|
|
QCOMPARE(itemHit->rect(), rect201Rect);
|
|
QCOMPARE(itemHit->text(QAccessible::Name), QLatin1String("rect201"));
|
|
|
|
delete canvas;
|
|
}
|
|
|
|
void tst_QQuickAccessible::checkableTest()
|
|
{
|
|
QQuickView *canvas = new QQuickView();
|
|
canvas->setSource(testFileUrl("checkbuttons.qml"));
|
|
canvas->show();
|
|
|
|
QAI iface = QAI(QAccessible::queryAccessibleInterface(canvas));
|
|
QVERIFY(iface.data());
|
|
QAI root = QAI(iface->child(0));
|
|
|
|
QAI button1 = QAI(root->child(0));
|
|
QCOMPARE(button1->role(), QAccessible::Button);
|
|
QVERIFY(!(button1->state().checked));
|
|
QAI button2 = QAI(root->child(1));
|
|
QVERIFY(!(button2->state().checked));
|
|
QAI button3 = QAI(root->child(2));
|
|
QVERIFY(button3->state().checked);
|
|
|
|
QAI checkBox1 = QAI(root->child(3));
|
|
QCOMPARE(checkBox1->role(), QAccessible::CheckBox);
|
|
QVERIFY((checkBox1->state().checked));
|
|
QAI checkBox2 = QAI(root->child(4));
|
|
QVERIFY(!(checkBox2->state().checked));
|
|
}
|
|
|
|
QTEST_MAIN(tst_QQuickAccessible)
|
|
|
|
#include "tst_qquickaccessible.moc"
|