summaryrefslogtreecommitdiffstats
path: root/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp')
-rw-r--r--tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp3372
1 files changed, 3372 insertions, 0 deletions
diff --git a/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp b/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp
new file mode 100644
index 0000000000..e1bd968534
--- /dev/null
+++ b/tests/auto/integrationtests/qaccessibility/tst_qaccessibility.cpp
@@ -0,0 +1,3372 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 <QtGui>
+#include <QtWidgets>
+#include <math.h>
+
+#if defined(Q_OS_WIN) && defined(interface)
+# undef interface
+#endif
+
+
+#include "QtTest/qtestaccessible.h"
+
+#if defined(Q_OS_WINCE)
+extern "C" bool SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
+#define SPI_GETPLATFORMTYPE 257
+inline bool IsValidCEPlatform() {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(*tszPlatform), tszPlatform, 0)) {
+ QString platform = QString::fromWCharArray(tszPlatform);
+ if ((platform == QLatin1String("PocketPC")) || (platform == QLatin1String("Smartphone")))
+ return false;
+ }
+ return true;
+}
+#endif
+
+static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
+ int index, const QRect &domain)
+{
+ if (!child) {
+ qWarning("tst_QAccessibility::verifyChild: null pointer to child.");
+ return false;
+ }
+
+ if (!interface) {
+ qWarning("tst_QAccessibility::verifyChild: null pointer to interface.");
+ return false;
+ }
+
+ // Verify that we get a valid QAccessibleInterface for the child.
+ QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child);
+ if (!childInterface) {
+ qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child.");
+ return false;
+ }
+
+ // QAccessibleInterface::indexOfChild():
+ // Verify that indexOfChild() returns an index equal to the index passed in
+ int indexFromIndexOfChild = interface->indexOfChild(childInterface);
+ delete childInterface;
+ if (indexFromIndexOfChild != index) {
+ qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
+ qWarning() << "Expected:" << index;
+ qWarning() << "Actual: " << indexFromIndexOfChild;
+ return false;
+ }
+
+ // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child).
+ QAccessibleInterface *navigatedChildInterface = interface->child(index - 1);
+ if (navigatedChildInterface == 0)
+ return false;
+
+ const QRect rectFromInterface = navigatedChildInterface->rect();
+ delete navigatedChildInterface;
+
+ // QAccessibleInterface::childAt():
+ // Calculate global child position and check that the interface
+ // returns the correct index for that position.
+ QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
+ int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y());
+ if (indexFromChildAt != index) {
+ qWarning("tst_QAccessibility::verifyChild (childAt()):");
+ qWarning() << "Expected:" << index;
+ qWarning() << "Actual: " << indexFromChildAt;
+ return false;
+ }
+
+ // QAccessibleInterface::rect():
+ // Calculate global child geometry and check that the interface
+ // returns a QRect which is equal to the calculated QRect.
+ const QRect expectedGlobalRect = QRect(globalChildPos, child->size());
+ if (expectedGlobalRect != rectFromInterface) {
+ qWarning("tst_QAccessibility::verifyChild (rect()):");
+ qWarning() << "Expected:" << expectedGlobalRect;
+ qWarning() << "Actual: " << rectFromInterface;
+ return false;
+ }
+
+ // Verify that the child is within its domain.
+ if (!domain.contains(rectFromInterface)) {
+ qWarning("tst_QAccessibility::verifyChild: Child is not within its domain.");
+ return false;
+ }
+
+ return true;
+}
+
+static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget)
+{
+ if (!parentInterface || !childWidget)
+ return -1;
+ QAccessibleInterface *childInterface = QAccessibleInterface::queryAccessibleInterface(childWidget);
+ if (!childInterface)
+ return -1;
+ int index = parentInterface->indexOfChild(childInterface);
+ delete childInterface;
+ return index;
+}
+
+#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 = 0;
+ parent = if2->parent();
+ EXPECT(iface->object() == parent->object());
+ delete parent;
+
+ // navigate Sibling...
+// if (middleChild) {
+// entry = if2->navigate(QAccessible::Sibling, middle, &if3);
+// EXPECT(entry == 0 && if3->object() == middleChild->object());
+// if (entry == 0)
+// delete if3;
+// EXPECT(iface->indexOfChild(middleChild) == middle);
+// }
+
+ // verify children...
+ if (!errorAt)
+ errorAt = verifyHierarchy(if2);
+ delete if2;
+ }
+ delete middleChild;
+
+ --treelevel;
+ return errorAt;
+}
+
+
+//TESTED_FILES=
+
+class tst_QAccessibility : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAccessibility();
+ virtual ~tst_QAccessibility();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void eventTest();
+ void customWidget();
+ void deletedWidget();
+
+ void navigateGeometric();
+ void navigateHierarchy();
+ void sliderTest();
+ void navigateCovered();
+ void textAttributes();
+ void hideShowTest();
+
+ void actionTest();
+
+ void applicationTest();
+ void mainWindowTest();
+ void buttonTest();
+ void scrollBarTest();
+ void tabTest();
+ void tabWidgetTest();
+ void menuTest();
+ void spinBoxTest();
+ void doubleSpinBoxTest();
+ void textEditTest();
+ void textBrowserTest();
+ void mdiAreaTest();
+ void mdiSubWindowTest();
+ void lineEditTest();
+ void workspaceTest();
+ void dialogButtonBoxTest();
+ void dialTest();
+ void rubberBandTest();
+ void abstractScrollAreaTest();
+ void scrollAreaTest();
+
+ // Accessible table1 interface is no longer supported on X11,
+ // where it has been replaced by table2 interface.
+#ifndef Q_OS_UNIX
+ void listViewTest();
+ void treeWidgetTest();
+ void tableWidgetTest();
+ void tableViewTest();
+#else
+ void table2ListTest();
+ void table2TreeTest();
+ void table2TableTest();
+#endif
+
+ void calendarWidgetTest();
+ void dockWidgetTest();
+ void comboBoxTest();
+ void accessibleName();
+ void labelTest();
+ void accelerators();
+};
+
+const double Q_PI = 3.14159265358979323846;
+
+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 0x0116: return "TableModelChanged";
+ case 0x011B: return "TextCaretMoved";
+
+ 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";
+ }
+}
+
+QAccessible::State state(QWidget * const widget)
+{
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
+ if (!iface)
+ qWarning() << "Cannot get QAccessibleInterface for widget";
+ QAccessible::State state = (iface ? iface->state() : static_cast<QAccessible::State>(0));
+ delete iface;
+ return state;
+}
+
+class QtTestAccessibleWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
+ {
+ setObjectName(name);
+ QPalette pal;
+ pal.setColor(backgroundRole(), Qt::black);//black is beautiful
+ setPalette(pal);
+ setFixedSize(5, 5);
+ }
+};
+
+class QtTestAccessibleWidgetIface: public QAccessibleWidget
+{
+public:
+ QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
+ QString text(Text t, int control = 0) const
+ {
+ if (t == Help)
+ return QString::fromLatin1("Help yourself");
+ return QAccessibleWidget::text(t, control);
+ }
+ static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
+ {
+ if (key == "QtTestAccessibleWidget")
+ return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
+ return 0;
+ }
+};
+
+tst_QAccessibility::tst_QAccessibility()
+{
+}
+
+tst_QAccessibility::~tst_QAccessibility()
+{
+}
+
+void tst_QAccessibility::initTestCase()
+{
+ QTestAccessibility::initialize();
+ QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
+}
+
+void tst_QAccessibility::cleanupTestCase()
+{
+ QTestAccessibility::cleanup();
+}
+
+void tst_QAccessibility::init()
+{
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::cleanup()
+{
+ const EventList list = QTestAccessibility::events();
+ if (!list.isEmpty()) {
+ qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
+ QString(QTest::currentTestFunction()).toAscii().constData());
+ for (int i = 0; i < list.count(); ++i)
+ qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
+ eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::eventTest()
+{
+ QPushButton* button = new QPushButton(0);
+ button->setObjectName(QString("Olaf"));
+
+ button->show();
+ QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
+ button->setFocus(Qt::MouseFocusReason);
+ QTestAccessibility::clearEvents();
+ QTest::mouseClick(button, Qt::LeftButton, 0);
+ QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
+ QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
+
+ button->setAccessibleName("Olaf the second");
+ QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
+ button->setAccessibleDescription("This is a button labeled Olaf");
+ QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
+
+ button->hide();
+ QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
+
+ delete button;
+}
+
+void tst_QAccessibility::customWidget()
+{
+ QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+ QCOMPARE(iface->object(), (QObject*)widget);
+ QCOMPARE(iface->object()->objectName(), QString("Heinz"));
+ QCOMPARE(iface->text(QAccessible::Help, 0), QString("Help yourself"));
+
+ delete iface;
+ delete widget;
+}
+
+void tst_QAccessibility::deletedWidget()
+{
+ QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+ QCOMPARE(iface->object(), (QObject*)widget);
+
+ delete widget;
+ widget = 0;
+ QVERIFY(!iface->isValid());
+ delete iface;
+}
+
+void tst_QAccessibility::navigateGeometric()
+{
+ {
+ static const int skip = 20; //speed the test up significantly
+ static const double step = Q_PI / 180;
+ QWidget *w = new QWidget(0);
+ w->setObjectName(QString("Josef"));
+ w->setFixedSize(400, 400);
+
+ // center widget
+ QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol");
+ center->move(200, 200);
+
+ // arrange 360 widgets around it in a circle
+ QtTestAccessibleWidget *aw = 0;
+ for (int i = 0; i < 360; i += skip) {
+ aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1());
+ aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) );
+ }
+
+ aw = new QtTestAccessibleWidget(w, "Earth");
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center);
+ QAccessibleInterface *target = 0;
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+
+ w->show();
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ // let one widget rotate around center
+ for (int i = 0; i < 360; i+=skip) {
+ aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) );
+
+ if (i < 45 || i > 315) {
+ QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
+ } else if ( i < 135 ) {
+ QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
+ } else if ( i < 225 ) {
+ QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
+ } else {
+ QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
+ }
+
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QVERIFY(target->object());
+ QCOMPARE(target->object()->objectName(), aw->objectName());
+ delete target; target = 0;
+ }
+
+ // test invisible widget
+ target = QAccessible::queryAccessibleInterface(aw);
+ QVERIFY(!(target->state() & QAccessible::Invisible));
+ aw->hide();
+ QVERIFY(target->state() & QAccessible::Invisible);
+ delete target; target = 0;
+
+ aw->move(center->x() + 10, center->y());
+ QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QVERIFY(target->object());
+ QVERIFY(QString(target->object()->objectName()) != "Earth");
+ delete target; target = 0;
+
+ aw->move(center->x() - 10, center->y());
+ QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QVERIFY(target->object());
+ QVERIFY(QString(target->object()->objectName()) != "Earth");
+ delete target; target = 0;
+
+ aw->move(center->x(), center->y() + 10);
+ QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QVERIFY(target->object());
+ QVERIFY(QString(target->object()->objectName()) != "Earth");
+ delete target; target = 0;
+
+ aw->move(center->x(), center->y() - 10);
+ QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QVERIFY(target->object());
+ QVERIFY(QString(target->object()->objectName()) != "Earth");
+ delete target; target = 0;
+
+ delete iface;
+ delete w;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::sliderTest()
+{
+ {
+ QSlider *slider = new QSlider(0);
+ slider->setObjectName(QString("Slidy"));
+ slider->show();
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+
+ QCOMPARE(iface->childCount(), 0);
+ QCOMPARE(iface->role(), QAccessible::Slider);
+
+ QAccessibleValueInterface *valueIface = iface->valueInterface();
+ QVERIFY(valueIface != 0);
+ QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum());
+ QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum());
+ slider->setValue(50);
+ QCOMPARE(valueIface->currentValue().toInt(), slider->value());
+ slider->setValue(0);
+ QCOMPARE(valueIface->currentValue().toInt(), slider->value());
+ slider->setValue(100);
+ QCOMPARE(valueIface->currentValue().toInt(), slider->value());
+ valueIface->setCurrentValue(77);
+ QCOMPARE(77, slider->value());
+
+ delete iface;
+ delete slider;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::navigateCovered()
+{
+ {
+ QWidget *w = new QWidget(0);
+ w->setObjectName(QString("Harry"));
+ QWidget *w1 = new QWidget(w);
+ w1->setObjectName(QString("1"));
+ QWidget *w2 = new QWidget(w);
+ w2->setObjectName(QString("2"));
+ w->show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+
+ w->setFixedSize(6, 6);
+ w1->setFixedSize(5, 5);
+ w2->setFixedSize(5, 5);
+ w2->move(0, 0);
+ w1->raise();
+
+ QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1);
+ QVERIFY(iface1 != 0);
+ QVERIFY(iface1->isValid());
+ QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2);
+ QVERIFY(iface2 != 0);
+ QVERIFY(iface2->isValid());
+ QAccessibleInterface *iface3 = 0;
+
+ QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1);
+ QVERIFY(iface3 == 0);
+
+ for (int loop = 0; loop < 2; ++loop) {
+ for (int x = 0; x < w->width(); ++x) {
+ for (int y = 0; y < w->height(); ++y) {
+ w1->move(x, y);
+ if (w1->geometry().intersects(w2->geometry())) {
+ QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers);
+ QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered);
+ QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0);
+ QVERIFY(iface3 != 0);
+ QVERIFY(iface3->isValid());
+ QCOMPARE(iface3->object(), iface2->object());
+ delete iface3; iface3 = 0;
+ QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0);
+ QVERIFY(iface3 != 0);
+ QVERIFY(iface3->isValid());
+ QCOMPARE(iface3->object(), iface1->object());
+ delete iface3; iface3 = 0;
+ } else {
+ QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers));
+ QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered));
+ QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ }
+ }
+ }
+ if (!loop) {
+ // switch children for second loop
+ w2->raise();
+ QAccessibleInterface *temp = iface1;
+ iface1 = iface2;
+ iface2 = temp;
+ }
+ }
+ delete iface1; iface1 = 0;
+ delete iface2; iface2 = 0;
+ iface1 = QAccessible::queryAccessibleInterface(w1);
+ QVERIFY(iface1 != 0);
+ QVERIFY(iface1->isValid());
+ iface2 = QAccessible::queryAccessibleInterface(w2);
+ QVERIFY(iface2 != 0);
+ QVERIFY(iface2->isValid());
+
+ w1->move(0,0);
+ w2->move(0,0);
+ w1->raise();
+ QVERIFY(iface1->relationTo(0, iface2, 0) & QAccessible::Covers);
+ QVERIFY(iface2->relationTo(0, iface1, 0) & QAccessible::Covered);
+ QVERIFY(!(iface1->state() & QAccessible::Invisible));
+ w1->hide();
+ QVERIFY(iface1->state() & QAccessible::Invisible);
+ QVERIFY(!(iface1->relationTo(0, iface2, 0) & QAccessible::Covers));
+ QVERIFY(!(iface2->relationTo(0, iface1, 0) & QAccessible::Covered));
+ QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+ QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
+ QVERIFY(iface3 == 0);
+
+ delete iface1; iface1 = 0;
+ delete iface2; iface2 = 0;
+ delete w;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::navigateHierarchy()
+{
+ {
+ QWidget *w = new QWidget(0);
+ w->setObjectName(QString("Hans"));
+ w->show();
+ QWidget *w1 = new QWidget(w);
+ w1->setObjectName(QString("1"));
+ w1->show();
+ QWidget *w2 = new QWidget(w);
+ w2->setObjectName(QString("2"));
+ w2->show();
+ QWidget *w3 = new QWidget(w);
+ w3->setObjectName(QString("3"));
+ w3->show();
+ QWidget *w31 = new QWidget(w3);
+ w31->setObjectName(QString("31"));
+ w31->show();
+
+ QAccessibleInterface *target = 0;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+
+ QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1);
+ QVERIFY(target == 0);
+ QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1);
+ QVERIFY(target == 0);
+
+ target = iface->child(14);
+ QVERIFY(target == 0);
+ target = iface->child(-1);
+ QVERIFY(target == 0);
+ target = iface->child(0);
+ QAccessibleInterface *interfaceW1 = iface->child(0);
+ QVERIFY(target);
+ QVERIFY(target->isValid());
+ QCOMPARE(target->object(), (QObject*)w1);
+ QVERIFY(interfaceW1 != 0);
+ QVERIFY(interfaceW1->isValid());
+ QCOMPARE(interfaceW1->object(), (QObject*)w1);
+ delete interfaceW1;
+ delete iface; iface = 0;
+
+ QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1);
+ QVERIFY(iface == 0);
+ QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1);
+ QVERIFY(iface == 0);
+ QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1);
+ QVERIFY(iface == 0);
+ QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+ QCOMPARE(iface->object(), (QObject*)w2);
+ delete target; target = 0;
+ QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0);
+ QVERIFY(target != 0);
+ QVERIFY(target->isValid());
+ QCOMPARE(target->object(), (QObject*)w3);
+ delete iface; iface = 0;
+
+ iface = target->child(0);
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+ QCOMPARE(iface->object(), (QObject*)w31);
+ delete target; target = 0;
+
+ QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1);
+ QVERIFY(target == 0);
+ QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1);
+ QVERIFY(target == 0);
+ QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0);
+ QVERIFY(target != 0);
+ QVERIFY(target->isValid());
+ QCOMPARE(target->object(), (QObject*)w31);
+ delete iface; iface = 0;
+
+ iface = target->parent();
+ QVERIFY(iface != 0);
+ QVERIFY(iface->isValid());
+ QCOMPARE(iface->object(), (QObject*)w3);
+ delete iface; iface = 0;
+ delete target; target = 0;
+
+ delete w;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+#define QSETCOMPARE(thetypename, elements, otherelements) \
+ QCOMPARE((QSet<thetypename>() << elements), (QSet<thetypename>() << otherelements))
+
+static QWidget *createWidgets()
+{
+ QWidget *w = new QWidget();
+
+ QHBoxLayout *box = new QHBoxLayout(w);
+
+ int i = 0;
+ box->addWidget(new QComboBox(w));
+ box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QHeaderView(Qt::Vertical, w));
+ box->addWidget(new QTreeView(w));
+ box->addWidget(new QTreeWidget(w));
+ box->addWidget(new QListView(w));
+ box->addWidget(new QListWidget(w));
+ box->addWidget(new QTableView(w));
+ box->addWidget(new QTableWidget(w));
+ box->addWidget(new QCalendarWidget(w));
+ box->addWidget(new QDialogButtonBox(w));
+ box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QFrame(w));
+ box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QProgressBar(w));
+ box->addWidget(new QTabWidget(w));
+ box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QDial(w));
+ box->addWidget(new QScrollBar(w));
+ box->addWidget(new QSlider(w));
+ box->addWidget(new QDateTimeEdit(w));
+ box->addWidget(new QDoubleSpinBox(w));
+ box->addWidget(new QSpinBox(w));
+ box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QLCDNumber(w));
+ box->addWidget(new QStackedWidget(w));
+ box->addWidget(new QToolBox(w));
+ box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
+ box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
+
+ /* Not in the list
+ * QAbstractItemView, QGraphicsView, QScrollArea,
+ * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
+ * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
+ */
+ return w;
+}
+
+void tst_QAccessibility::accessibleName()
+{
+ QWidget *toplevel = createWidgets();
+ toplevel->show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+ QLayout *lout = toplevel->layout();
+ for (int i = 0; i < lout->count(); i++) {
+ QLayoutItem *item = lout->itemAt(i);
+ QWidget *child = item->widget();
+
+ QString name = tr("Widget Name %1").arg(i);
+ child->setAccessibleName(name);
+ QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
+ QCOMPARE(acc->text(QAccessible::Name), name);
+
+ QString desc = tr("Widget Description %1").arg(i);
+ child->setAccessibleDescription(desc);
+ QCOMPARE(acc->text(QAccessible::Description), desc);
+
+ }
+
+ delete toplevel;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::textAttributes()
+{
+ QTextEdit textEdit;
+ int startOffset;
+ int endOffset;
+ QString attributes;
+ QString text("<html><head></head><body>"
+ "Hello, <b>this</b> is an <i><b>example</b> text</i>."
+ "<span style=\"font-family: monospace\">Multiple fonts are used.</span>"
+ "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used."
+ "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."
+ "</body></html>");
+
+ textEdit.setText(text);
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit);
+
+ QAccessibleTextInterface *textInterface=interface->textInterface();
+
+ QVERIFY(textInterface);
+ QCOMPARE(textInterface->characterCount(), 112);
+
+ attributes = textInterface->attributes(10, &startOffset, &endOffset);
+ QCOMPARE(startOffset, 7);
+ QCOMPARE(endOffset, 11);
+ attributes.prepend(';');
+ QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
+
+ attributes = textInterface->attributes(18, &startOffset, &endOffset);
+ QCOMPARE(startOffset, 18);
+ QCOMPARE(endOffset, 25);
+ attributes.prepend(';');
+ QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
+ QVERIFY(attributes.contains(QLatin1String(";font-style:italic;")));
+
+ attributes = textInterface->attributes(34, &startOffset, &endOffset);
+ QCOMPARE(startOffset, 31);
+ QCOMPARE(endOffset, 55);
+ attributes.prepend(';');
+ QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";")));
+
+ attributes = textInterface->attributes(65, &startOffset, &endOffset);
+ QCOMPARE(startOffset, 64);
+ QCOMPARE(endOffset, 74);
+ attributes.prepend(';');
+ QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;")));
+
+ attributes = textInterface->attributes(110, &startOffset, &endOffset);
+ QCOMPARE(startOffset, 109);
+ QCOMPARE(endOffset, 111);
+ attributes.prepend(';');
+ QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);")));
+ QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);")));
+}
+
+void tst_QAccessibility::hideShowTest()
+{
+ QWidget * const window = new QWidget();
+ QWidget * const child = new QWidget(window);
+
+ QVERIFY(state(window) & QAccessible::Invisible);
+ QVERIFY(state(child) & QAccessible::Invisible);
+
+ QTestAccessibility::clearEvents();
+
+ // show() and veryfy that both window and child are not invisible and get ObjectShow events.
+ window->show();
+ QVERIFY(state(window) ^ QAccessible::Invisible);
+ QVERIFY(state(child) ^ QAccessible::Invisible);
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
+ QTestAccessibility::clearEvents();
+
+ // hide() and veryfy that both window and child are invisible and get ObjectHide events.
+ window->hide();
+ QVERIFY(state(window) & QAccessible::Invisible);
+ QVERIFY(state(child) & QAccessible::Invisible);
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
+ QTestAccessibility::clearEvents();
+
+ delete window;
+ QTestAccessibility::clearEvents();
+}
+
+
+void tst_QAccessibility::actionTest()
+{
+ QCOMPARE(QAccessibleActionInterface::PressAction, QString("Press"));
+
+ QWidget *widget = new QWidget;
+ widget->show();
+
+ QAccessibleInterface *test = QAccessible::queryAccessibleInterface(widget);
+ QVERIFY(test);
+ QVERIFY(test->isValid());
+
+// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString());
+// QCOMPARE(test->actionText(0, QAccessible::Name, 1), QString());
+// QCOMPARE(test->actionText(1, QAccessible::Name, 1), QString());
+// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, -1), QString());
+
+// QCOMPARE(test->actionText(QAccessible::DefaultAction, QAccessible::Name, 0), QString("SetFocus"));
+// QCOMPARE(test->actionText(QAccessible::SetFocus, QAccessible::Name, 0), QString("SetFocus"));
+
+ delete test;
+ delete widget;
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::applicationTest()
+{
+ QLatin1String name = QLatin1String("My Name");
+ qApp->setApplicationName(name);
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp);
+ QCOMPARE(interface->text(QAccessible::Name, 0), name);
+ QCOMPARE(interface->role(), QAccessible::Application);
+ delete interface;
+}
+
+void tst_QAccessibility::mainWindowTest()
+{
+ QMainWindow *mw = new QMainWindow;
+ mw->resize(300, 200);
+ mw->show(); // triggers layout
+
+ QLatin1String name = QLatin1String("I am the main window");
+ mw->setWindowTitle(name);
+ QTest::qWaitForWindowShown(mw);
+ QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
+ QCOMPARE(interface->text(QAccessible::Name, 0), name);
+ QCOMPARE(interface->role(), QAccessible::Window);
+ delete interface;
+ delete mw;
+ QTestAccessibility::clearEvents();
+}
+
+class CounterButton : public QPushButton {
+ Q_OBJECT
+public:
+ CounterButton(const QString& name, QWidget* parent)
+ : QPushButton(name, parent), clickCount(0)
+ {
+ connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount()));
+ }
+ int clickCount;
+public Q_SLOTS:
+ void incClickCount() {
+ ++clickCount;
+ }
+};
+
+void tst_QAccessibility::buttonTest()
+{
+ QWidget window;
+ window.setLayout(new QVBoxLayout);
+
+ // Standard push button
+ CounterButton pushButton("Ok", &window);
+
+ // toggle button
+ QPushButton toggleButton("Toggle", &window);
+ toggleButton.setCheckable(true);
+
+ // standard checkbox
+ QCheckBox checkBox("Check me!", &window);
+
+ // tristate checkbox
+ QCheckBox tristate("Tristate!", &window);
+ tristate.setTristate(TRUE);
+
+ // radiobutton
+ QRadioButton radio("Radio me!", &window);
+
+ // standard toolbutton
+ QToolButton toolbutton(&window);
+ toolbutton.setText("Tool");
+ toolbutton.setMinimumSize(20,20);
+
+ // standard toolbutton
+ QToolButton toggletool(&window);
+ toggletool.setCheckable(true);
+ toggletool.setText("Toggle");
+ toggletool.setMinimumSize(20,20);
+
+ // test push button
+ QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton);
+ QAccessibleActionInterface* actionInterface = interface->actionInterface();
+ QVERIFY(actionInterface != 0);
+ QCOMPARE(interface->role(), QAccessible::PushButton);
+
+ // currently our buttons only have click as action, press and release are missing
+ QCOMPARE(actionInterface->actionNames().size(), 1);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+ QCOMPARE(pushButton.clickCount, 0);
+ actionInterface->doAction(QAccessibleActionInterface::PressAction);
+ QTest::qWait(500);
+ QCOMPARE(pushButton.clickCount, 1);
+ delete interface;
+
+ // test toggle button
+ interface = QAccessible::queryAccessibleInterface(&toggleButton);
+ actionInterface = interface->actionInterface();
+ QCOMPARE(interface->role(), QAccessible::CheckBox);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction);
+ QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::CheckAction), QString("Checks the checkbox"));
+ QVERIFY(!toggleButton.isChecked());
+ QVERIFY((interface->state() & QAccessible::Checked) == 0);
+ actionInterface->doAction(QAccessibleActionInterface::CheckAction);
+ QTest::qWait(500);
+ QVERIFY(toggleButton.isChecked());
+ QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::UncheckAction);
+ QVERIFY(interface->state() & QAccessible::Checked);
+ delete interface;
+
+ {
+ // test menu push button
+ QAction *foo = new QAction("Foo", 0);
+ foo->setShortcut(QKeySequence("Ctrl+F"));
+ QMenu *menu = new QMenu();
+ menu->addAction(foo);
+ QPushButton menuButton;
+ menuButton.setMenu(menu);
+ menuButton.show();
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
+ QCOMPARE(interface->role(), QAccessible::ButtonMenu);
+ QVERIFY(interface->state() & QAccessible::HasPopup);
+ QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction);
+ // showing the menu enters a new event loop...
+// interface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+// QTest::qWait(500);
+ delete interface;
+ delete menu;
+ }
+
+ // test check box
+ interface = QAccessible::queryAccessibleInterface(&checkBox);
+ actionInterface = interface->actionInterface();
+ QCOMPARE(interface->role(), QAccessible::CheckBox);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction);
+ QVERIFY((interface->state() & QAccessible::Checked) == 0);
+ actionInterface->doAction(QAccessibleActionInterface::CheckAction);
+ QTest::qWait(500);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::UncheckAction);
+ QVERIFY(interface->state() & QAccessible::Checked);
+ QVERIFY(checkBox.isChecked());
+ delete interface;
+
+ // test radiobutton
+ interface = QAccessible::queryAccessibleInterface(&radio);
+ actionInterface = interface->actionInterface();
+ QCOMPARE(interface->role(), QAccessible::RadioButton);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction);
+ QVERIFY((interface->state() & QAccessible::Checked) == 0);
+ actionInterface->doAction(QAccessibleActionInterface::CheckAction);
+ QTest::qWait(500);
+ QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::CheckAction);
+ QVERIFY(interface->state() & QAccessible::Checked);
+ QVERIFY(checkBox.isChecked());
+ delete interface;
+
+// // test standard toolbutton
+// QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
+// QCOMPARE(test->role(), QAccessible::PushButton);
+// QCOMPARE(test->defaultAction(0), QAccessible::Press);
+// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
+// QCOMPARE(test->state(), (int)QAccessible::Normal);
+// test->release();
+
+// // toggle tool button
+// QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test));
+// QCOMPARE(test->role(), QAccessible::CheckBox);
+// QCOMPARE(test->defaultAction(0), QAccessible::Press);
+// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check"));
+// QCOMPARE(test->state(), (int)QAccessible::Normal);
+// QVERIFY(test->doAction(QAccessible::Press, 0));
+// QTest::qWait(500);
+// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck"));
+// QCOMPARE(test->state(), (int)QAccessible::Checked);
+// test->release();
+
+// // test menu toolbutton
+// QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test));
+// QCOMPARE(test->role(), QAccessible::ButtonMenu);
+// QCOMPARE(test->defaultAction(0), 1);
+// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open"));
+// QCOMPARE(test->state(), (int)QAccessible::HasPopup);
+// QCOMPARE(test->actionCount(0), 1);
+// QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
+// test->release();
+
+// // test split menu toolbutton
+// QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
+// QCOMPARE(test->childCount(), 2);
+// QCOMPARE(test->role(), QAccessible::ButtonDropDown);
+// QCOMPARE(test->role(1), QAccessible::PushButton);
+// QCOMPARE(test->role(2), QAccessible::ButtonMenu);
+// QCOMPARE(test->defaultAction(0), QAccessible::Press);
+// QCOMPARE(test->defaultAction(1), QAccessible::Press);
+// QCOMPARE(test->defaultAction(2), QAccessible::Press);
+// QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
+// QCOMPARE(test->state(), (int)QAccessible::HasPopup);
+// QCOMPARE(test->actionCount(0), 1);
+// QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open"));
+// QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press"));
+// QCOMPARE(test->state(1), (int)QAccessible::Normal);
+// QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
+// QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
+// test->release();
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::scrollBarTest()
+{
+ QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
+ QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
+ QVERIFY(scrollBarInterface);
+ QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
+ scrollBar->resize(200, 50);
+ scrollBar->show();
+ QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible);
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
+ QTestAccessibility::clearEvents();
+
+ scrollBar->hide();
+ QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
+ QTestAccessibility::clearEvents();
+
+ // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
+ scrollBar->show();
+ scrollBar->setMinimum(11);
+ scrollBar->setMaximum(111);
+
+ QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface();
+ QVERIFY(valueIface != 0);
+ QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum());
+ QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum());
+ scrollBar->setValue(50);
+ QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
+ scrollBar->setValue(0);
+ QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
+ scrollBar->setValue(100);
+ QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
+ valueIface->setCurrentValue(77);
+ QCOMPARE(77, scrollBar->value());
+
+ const QRect scrollBarRect = scrollBarInterface->rect();
+ QVERIFY(scrollBarRect.isValid());
+
+ delete scrollBarInterface;
+ delete scrollBar;
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::tabTest()
+{
+ QTabBar *tabBar = new QTabBar();
+ tabBar->show();
+
+ QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 2);
+
+ // Test that the Invisible bit for the navigation buttons gets set
+ // and cleared correctly.
+ QAccessibleInterface *leftButton = interface->child(0);
+ QCOMPARE(leftButton->role(), QAccessible::PushButton);
+ QVERIFY(leftButton->state() & QAccessible::Invisible);
+ delete leftButton;
+
+ const int lots = 5;
+ for (int i = 0; i < lots; ++i)
+ tabBar->addTab("Foo");
+
+ QAccessibleInterface *child1 = interface->child(0);
+ QAccessibleInterface *child2 = interface->child(1);
+ QVERIFY(child1);
+ QCOMPARE(child1->role(), QAccessible::PageTab);
+ QVERIFY(child2);
+ QCOMPARE(child2->role(), QAccessible::PageTab);
+
+ QVERIFY((child1->state() & QAccessible::Invisible) == false);
+ tabBar->hide();
+
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ QVERIFY(child1->state() & QAccessible::Invisible);
+
+ tabBar->show();
+ tabBar->setCurrentIndex(0);
+
+ // Test that sending a focus action to a tab does not select it.
+// child2->doAction(QAccessible::Focus, 2, QVariantList());
+ QCOMPARE(tabBar->currentIndex(), 0);
+
+ // Test that sending a press action to a tab selects it.
+ QVERIFY(child2->actionInterface());
+ QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+ QCOMPARE(tabBar->currentIndex(), 0);
+ child2->actionInterface()->doAction(QAccessibleActionInterface::PressAction);
+ QCOMPARE(tabBar->currentIndex(), 1);
+
+ delete tabBar;
+ delete interface;
+ delete child1;
+ delete child2;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::tabWidgetTest()
+{
+ QTabWidget *tabWidget = new QTabWidget();
+ tabWidget->show();
+
+ // the interface for the tab is just a container for tabbar and stacked widget
+ QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 2);
+ QCOMPARE(interface->role(), QAccessible::Client);
+
+ // Create pages, check navigation
+ QLabel *label1 = new QLabel("Page 1", tabWidget);
+ tabWidget->addTab(label1, "Tab 1");
+ QLabel *label2 = new QLabel("Page 2", tabWidget);
+ tabWidget->addTab(label2, "Tab 2");
+
+ QCOMPARE(interface->childCount(), 2);
+
+ QAccessibleInterface* tabBarInterface = 0;
+ // there is no special logic to sort the children, so the contents will be 1, the tab bar 2
+ tabBarInterface = interface->child(1);
+ QVERIFY(tabBarInterface);
+ QCOMPARE(tabBarInterface->childCount(), 4);
+ QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList);
+
+ QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0);
+ QVERIFY(tabButton1Interface);
+ QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab);
+ QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1"));
+
+ QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1);
+ QVERIFY(tabButton1Interface);
+ QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab);
+ QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2"));
+
+ QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2);
+ QVERIFY(tabButtonLeft);
+ QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton);
+ QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left"));
+
+ QAccessibleInterface* tabButtonRight = tabBarInterface->child(3);
+ QVERIFY(tabButtonRight);
+ QCOMPARE(tabButtonRight->role(), QAccessible::PushButton);
+ QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right"));
+ delete tabButton1Interface;
+ delete tabButton2Interface;
+ delete tabButtonLeft;
+ delete tabButtonRight;
+
+ QAccessibleInterface* stackWidgetInterface = interface->child(0);
+ QVERIFY(stackWidgetInterface);
+ QCOMPARE(stackWidgetInterface->childCount(), 2);
+ QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane);
+
+ QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0);
+ QVERIFY(stackChild1Interface);
+#ifndef Q_CC_INTEL
+ QCOMPARE(stackChild1Interface->childCount(), 0);
+#endif
+ QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText);
+ QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1"));
+ QCOMPARE(label1, stackChild1Interface->object());
+
+ // Navigation in stack widgets should be consistent
+ QAccessibleInterface* parent = stackChild1Interface->parent();
+ QVERIFY(parent);
+#ifndef Q_CC_INTEL
+ QCOMPARE(parent->childCount(), 2);
+#endif
+ QCOMPARE(parent->role(), QAccessible::LayeredPane);
+ delete parent;
+
+ QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1);
+ QVERIFY(stackChild2Interface);
+ QCOMPARE(stackChild2Interface->childCount(), 0);
+ QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText);
+ QCOMPARE(label2, stackChild2Interface->object());
+ QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name));
+
+ parent = stackChild2Interface->parent();
+ QVERIFY(parent);
+#ifndef Q_CC_INTEL
+ QCOMPARE(parent->childCount(), 2);
+#endif
+ QCOMPARE(parent->role(), QAccessible::LayeredPane);
+ delete parent;
+
+ delete tabBarInterface;
+ delete stackChild1Interface;
+ delete stackChild2Interface;
+ delete stackWidgetInterface;
+ delete interface;
+ delete tabWidget;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::menuTest()
+{
+ {
+ QMainWindow mw;
+ mw.resize(300, 200);
+ QMenu *file = mw.menuBar()->addMenu("&File");
+ QMenu *fileNew = file->addMenu("&New...");
+ fileNew->menuAction()->setShortcut(tr("Ctrl+N"));
+ fileNew->addAction("Text file");
+ fileNew->addAction("Image file");
+ file->addAction("&Open")->setShortcut(tr("Ctrl+O"));
+ file->addAction("&Save")->setShortcut(tr("Ctrl+S"));
+ file->addSeparator();
+ file->addAction("E&xit")->setShortcut(tr("Alt+F4"));
+
+ QMenu *edit = mw.menuBar()->addMenu("&Edit");
+ edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z"));
+ edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y"));
+ edit->addSeparator();
+ edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X"));
+ edit->addAction("&Copy")->setShortcut(tr("Ctrl+C"));
+ edit->addAction("&Paste")->setShortcut(tr("Ctrl+V"));
+ edit->addAction("&Delete")->setShortcut(tr("Del"));
+ edit->addSeparator();
+ edit->addAction("Pr&operties");
+
+ mw.menuBar()->addSeparator();
+
+ QMenu *help = mw.menuBar()->addMenu("&Help");
+ help->addAction("&Contents");
+ help->addAction("&About");
+
+ mw.menuBar()->addAction("Action!");
+
+ mw.show(); // triggers layout
+ QTest::qWait(100);
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
+ QCOMPARE(verifyHierarchy(interface), 0);
+
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 5);
+ QCOMPARE(interface->role(), QAccessible::MenuBar);
+
+ QAccessibleInterface *iFile = interface->child(0);
+ QAccessibleInterface *iEdit = interface->child(1);
+ QAccessibleInterface *iSeparator = interface->child(2);
+ QAccessibleInterface *iHelp = interface->child(3);
+ QAccessibleInterface *iAction = interface->child(4);
+
+ QCOMPARE(iFile->role(), QAccessible::MenuItem);
+ QCOMPARE(iEdit->role(), QAccessible::MenuItem);
+ QCOMPARE(iSeparator->role(), QAccessible::Separator);
+ QCOMPARE(iHelp->role(), QAccessible::MenuItem);
+ QCOMPARE(iAction->role(), QAccessible::MenuItem);
+#ifndef Q_WS_MAC
+#ifdef Q_OS_WINCE
+ if (!IsValidCEPlatform()) {
+ QSKIP("Tests do not work on Mobile platforms due to native menus", SkipAll);
+ }
+#endif
+ QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft());
+ QCOMPARE(interface->rect().size(), mw.menuBar()->size());
+
+ QVERIFY(interface->rect().contains(iFile->rect()));
+ QVERIFY(interface->rect().contains(iEdit->rect()));
+ // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible
+ QVERIFY(interface->rect().contains(iHelp->rect()));
+ QVERIFY(interface->rect().contains(iAction->rect()));
+#endif
+
+ QCOMPARE(iFile->text(QAccessible::Name, 0), QString("File"));
+ QCOMPARE(iEdit->text(QAccessible::Name, 0), QString("Edit"));
+ QCOMPARE(iSeparator->text(QAccessible::Name, 0), QString());
+ QCOMPARE(iHelp->text(QAccessible::Name, 0), QString("Help"));
+ QCOMPARE(iAction->text(QAccessible::Name, 0), QString("Action!"));
+
+// TODO: Currently not working, task to fix is #100019.
+#ifndef Q_OS_MAC
+ QCOMPARE(iFile->text(QAccessible::Accelerator, 0), tr("Alt+F"));
+ QCOMPARE(iEdit->text(QAccessible::Accelerator, 0), tr("Alt+E"));
+ QCOMPARE(iSeparator->text(QAccessible::Accelerator, 0), QString());
+ QCOMPARE(iHelp->text(QAccessible::Accelerator, 0), tr("Alt+H"));
+ QCOMPARE(iAction->text(QAccessible::Accelerator, 0), QString());
+#endif
+
+ QVERIFY(iFile->actionInterface());
+
+ QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction);
+ QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList());
+ QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction);
+ QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+
+ bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu);
+ int menuFadeDelay = 300;
+ iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ if(menuFade)
+ QTest::qWait(menuFadeDelay);
+ QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible());
+ iEdit->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ if(menuFade)
+ QTest::qWait(menuFadeDelay);
+ QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible());
+ iHelp->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ if(menuFade)
+ QTest::qWait(menuFadeDelay);
+ QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible());
+ iAction->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ if(menuFade)
+ QTest::qWait(menuFadeDelay);
+ QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible());
+
+ QVERIFY(!interface->actionInterface());
+ delete interface;
+ interface = QAccessible::queryAccessibleInterface(file);
+ QCOMPARE(interface->childCount(), 5);
+ QCOMPARE(interface->role(), QAccessible::PopupMenu);
+
+ QAccessibleInterface *iFileNew = interface->child(0);
+ QAccessibleInterface *iFileOpen = interface->child(1);
+ QAccessibleInterface *iFileSave = interface->child(2);
+ QAccessibleInterface *iFileSeparator = interface->child(3);
+ QAccessibleInterface *iFileExit = interface->child(4);
+
+ QCOMPARE(iFileNew->role(), QAccessible::MenuItem);
+ QCOMPARE(iFileOpen->role(), QAccessible::MenuItem);
+ QCOMPARE(iFileSave->role(), QAccessible::MenuItem);
+ QCOMPARE(iFileSeparator->role(), QAccessible::Separator);
+ QCOMPARE(iFileExit->role(), QAccessible::MenuItem);
+ QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction);
+ QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+ QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+ QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList());
+ QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::PressAction);
+
+ QAccessibleInterface *iface = 0;
+ QAccessibleInterface *iface2 = 0;
+
+ // traverse siblings with navigate(Sibling, ...)
+ int entry = interface->navigate(QAccessible::Child, 1, &iface);
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::MenuItem);
+
+ QAccessible::Role fileRoles[5] = {
+ QAccessible::MenuItem,
+ QAccessible::MenuItem,
+ QAccessible::MenuItem,
+ QAccessible::Separator,
+ QAccessible::MenuItem
+ };
+ for (int child = 0; child < 5; ++child) {
+ entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2);
+ QCOMPARE(entry, 0);
+ QVERIFY(iface2);
+ QCOMPARE(iface2->role(), fileRoles[child]);
+ delete iface2;
+ }
+ delete iface;
+
+ // traverse menu items with navigate(Down, ...)
+ entry = interface->navigate(QAccessible::Child, 1, &iface);
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::MenuItem);
+
+ for (int child = 0; child < 4; ++child) {
+ entry = iface->navigate(QAccessible::Down, 1, &iface2);
+ delete iface;
+ iface = iface2;
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), fileRoles[child + 1]);
+ }
+ delete iface;
+
+ // traverse menu items with navigate(Up, ...)
+ entry = interface->navigate(QAccessible::Child, interface->childCount(), &iface);
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::MenuItem);
+
+ for (int child = 3; child >= 0; --child) {
+ entry = iface->navigate(QAccessible::Up, 1, &iface2);
+ delete iface;
+ iface = iface2;
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), fileRoles[child]);
+ }
+ delete iface;
+
+ // "New" item
+ entry = interface->navigate(QAccessible::Child, 1, &iface);
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::MenuItem);
+
+ // "New" menu
+ entry = iface->navigate(QAccessible::Child, 1, &iface2);
+ delete iface;
+ iface = iface2;
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::PopupMenu);
+
+ // "Text file" menu item
+ entry = iface->navigate(QAccessible::Child, 1, &iface2);
+ delete iface;
+ iface = iface2;
+ QCOMPARE(entry, 0);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::MenuItem);
+
+ delete iface;
+
+ // move mouse pointer away, since that might influence the
+ // subsequent tests
+ QTest::mouseMove(&mw, QPoint(-1, -1));
+ QTest::qWait(100);
+ if (menuFade)
+ QTest::qWait(menuFadeDelay);
+
+ iFile->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ iFileNew->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+
+ QVERIFY(file->isVisible());
+ QVERIFY(fileNew->isVisible());
+ QVERIFY(!edit->isVisible());
+ QVERIFY(!help->isVisible());
+
+ QTestAccessibility::clearEvents();
+ mw.hide();
+
+ delete iFile;
+ delete iFileNew;
+ delete iFileOpen;
+ delete iFileSave;
+ delete iFileSeparator;
+ delete iFileExit;
+
+ // Do not crash if the menu don't have a parent
+ QMenu *menu = new QMenu;
+ menu->addAction(QLatin1String("one"));
+ menu->addAction(QLatin1String("two"));
+ menu->addAction(QLatin1String("three"));
+ iface = QAccessible::queryAccessibleInterface(menu);
+ iface2 = iface->parent();
+ QVERIFY(iface2);
+ QCOMPARE(iface2->role(), QAccessible::Application);
+ // caused a *crash*
+ iface2->state();
+ delete iface2;
+ delete iface;
+ delete menu;
+
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::spinBoxTest()
+{
+ QSpinBox * const spinBox = new QSpinBox();
+ spinBox->setValue(3);
+ spinBox->show();
+
+ QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox);
+ QVERIFY(interface);
+ QCOMPARE(interface->role(), QAccessible::SpinBox);
+
+ const QRect widgetRect = spinBox->geometry();
+ const QRect accessibleRect = interface->rect();
+ QCOMPARE(accessibleRect, widgetRect);
+ QCOMPARE(interface->text(QAccessible::Value, 0), QLatin1String("3"));
+
+ // one child, the line edit
+ const int numChildren = interface->childCount();
+ QCOMPARE(numChildren, 1);
+ QAccessibleInterface *lineEdit = interface->child(0);
+
+ QCOMPARE(lineEdit->role(), QAccessible::EditableText);
+ QCOMPARE(lineEdit->text(QAccessible::Value, 0), QLatin1String("3"));
+ delete lineEdit;
+
+ QVERIFY(interface->valueInterface());
+ QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3);
+ interface->valueInterface()->setCurrentValue(23);
+ QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23);
+ QCOMPARE(spinBox->value(), 23);
+
+ spinBox->setFocus();
+ QTestAccessibility::clearEvents();
+ QTest::keyPress(spinBox, Qt::Key_Up);
+ QTest::qWait(200);
+ EventList events = QTestAccessibility::events();
+ QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
+ QVERIFY(events.contains(expectedEvent));
+ delete spinBox;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::doubleSpinBoxTest()
+{
+ QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox;
+ doubleSpinBox->show();
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
+ QVERIFY(interface);
+
+ const QRect widgetRect = doubleSpinBox->geometry();
+ const QRect accessibleRect = interface->rect();
+ QCOMPARE(accessibleRect, widgetRect);
+
+ // Test that we get valid rects for all the spinbox child interfaces.
+ const int numChildren = interface->childCount();
+ for (int i = 1; i <= numChildren; ++i) {
+ const QRect childRect = interface->rect(i);
+ QVERIFY(childRect.isValid());
+ }
+
+ delete doubleSpinBox;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::textEditTest()
+{
+ {
+ QTextEdit edit;
+ int startOffset;
+ int endOffset;
+ QString text = "hello world\nhow are you today?\n";
+ edit.setText(text);
+ edit.show();
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
+ QCOMPARE(iface->text(QAccessible::Value, 0), text);
+ QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
+ QCOMPARE(startOffset, 6);
+ QCOMPARE(endOffset, 11);
+ QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
+ QCOMPARE(startOffset, 12);
+ QCOMPARE(endOffset, 30);
+ QCOMPARE(iface->textInterface()->characterCount(), 31);
+ QFontMetrics fm(edit.font());
+ QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
+ QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
+ QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::textBrowserTest()
+{
+ {
+ QTextBrowser textBrowser;
+ QString text = QLatin1String("Hello world\nhow are you today?\n");
+ textBrowser.setText(text);
+ textBrowser.show();
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
+ QVERIFY(iface);
+ QCOMPARE(iface->role(), QAccessible::StaticText);
+ QCOMPARE(iface->text(QAccessible::Value, 0), text);
+ int startOffset;
+ int endOffset;
+ QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
+ QCOMPARE(startOffset, 6);
+ QCOMPARE(endOffset, 11);
+ QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
+ QCOMPARE(startOffset, 12);
+ QCOMPARE(endOffset, 30);
+ QCOMPARE(iface->textInterface()->characterCount(), 31);
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::mdiAreaTest()
+{
+ {
+ QMdiArea mdiArea;
+ mdiArea.resize(400,300);
+ mdiArea.show();
+ const int subWindowCount = 3;
+ for (int i = 0; i < subWindowCount; ++i)
+ mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show();
+
+ QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+ QCOMPARE(subWindows.count(), subWindowCount);
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), subWindowCount);
+
+ // Right, right, right, ...
+ for (int i = 0; i < subWindowCount; ++i) {
+ QAccessibleInterface *destination = 0;
+ int index = interface->navigate(QAccessible::Right, i + 1, &destination);
+ if (i == subWindowCount - 1) {
+ QVERIFY(!destination);
+ QCOMPARE(index, -1);
+ } else {
+ QVERIFY(destination);
+ QCOMPARE(index, 0);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
+ delete destination;
+ }
+ }
+
+ // Left, left, left, ...
+ for (int i = subWindowCount; i > 0; --i) {
+ QAccessibleInterface *destination = 0;
+ int index = interface->navigate(QAccessible::Left, i, &destination);
+ if (i == 1) {
+ QVERIFY(!destination);
+ QCOMPARE(index, -1);
+ } else {
+ QVERIFY(destination);
+ QCOMPARE(index, 0);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
+ delete destination;
+ }
+ }
+ // ### Add test for Up and Down.
+
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::mdiSubWindowTest()
+{
+ {
+ QMdiArea mdiArea;
+ mdiArea.show();
+ qApp->setActiveWindow(&mdiArea);
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(150);
+#endif
+
+ bool isSubWindowsPlacedNextToEachOther = false;
+ const int subWindowCount = 5;
+ for (int i = 0; i < subWindowCount; ++i) {
+ QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
+ window->show();
+ // Parts of this test requires that the sub windows are placed next
+ // to each other. In order to achieve that QMdiArea must have
+ // a width which is larger than subWindow->width() * subWindowCount.
+ if (i == 0) {
+ int minimumWidth = window->width() * subWindowCount + 20;
+ mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0)));
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+ if (mdiArea.width() >= minimumWidth)
+ isSubWindowsPlacedNextToEachOther = true;
+ }
+ }
+
+ QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+ QCOMPARE(subWindows.count(), subWindowCount);
+
+ QMdiSubWindow *testWindow = subWindows.at(3);
+ QVERIFY(testWindow);
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow);
+
+ // childCount
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 1);
+
+ // setText / text
+ QCOMPARE(interface->text(QAccessible::Name, 0), QString());
+ QCOMPARE(interface->text(QAccessible::Name, 1), QString());
+ testWindow->setWindowTitle(QLatin1String("ReplaceMe"));
+ QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("ReplaceMe"));
+ QCOMPARE(interface->text(QAccessible::Name, 1), QLatin1String("ReplaceMe"));
+ interface->setText(QAccessible::Name, 0, QLatin1String("TitleSetOnWindow"));
+ QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnWindow"));
+ interface->setText(QAccessible::Name, 1, QLatin1String("TitleSetOnChild"));
+ QCOMPARE(interface->text(QAccessible::Name, 0), QLatin1String("TitleSetOnChild"));
+
+ mdiArea.setActiveSubWindow(testWindow);
+
+ // state
+ QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused
+ | QAccessible::Movable | QAccessible::Sizeable;
+ QCOMPARE(interface->state(), state);
+ const QRect originalGeometry = testWindow->geometry();
+ testWindow->showMaximized();
+ state &= ~QAccessible::Sizeable;
+ state &= ~QAccessible::Movable;
+ QCOMPARE(interface->state(), state);
+ testWindow->showNormal();
+ testWindow->move(-10, 0);
+ QVERIFY(interface->state() & QAccessible::Offscreen);
+ testWindow->setVisible(false);
+ QVERIFY(interface->state() & QAccessible::Invisible);
+ testWindow->setVisible(true);
+ testWindow->setEnabled(false);
+ QVERIFY(interface->state() & QAccessible::Unavailable);
+ testWindow->setEnabled(true);
+ qApp->setActiveWindow(&mdiArea);
+ mdiArea.setActiveSubWindow(testWindow);
+ testWindow->setFocus();
+ QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
+ QVERIFY(interface->state() & QAccessible::Focused);
+ testWindow->setGeometry(originalGeometry);
+
+ if (isSubWindowsPlacedNextToEachOther) {
+ // This part of the test can only be run if the sub windows are
+ // placed next to each other.
+ QAccessibleInterface *destination = 0;
+ QCOMPARE(interface->navigate(QAccessible::Child, 1, &destination), 0);
+ QVERIFY(destination);
+ QCOMPARE(destination->object(), (QObject*)testWindow->widget());
+ delete destination;
+ QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0);
+ QVERIFY(destination);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(2));
+ delete destination;
+ QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0);
+ QVERIFY(destination);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(4));
+ delete destination;
+ }
+
+ // rect
+ const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0));
+ QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size()));
+ testWindow->hide();
+ QCOMPARE(interface->rect(), QRect());
+ QCOMPARE(interface->rect(1), QRect());
+ testWindow->showMinimized();
+ QCOMPARE(interface->rect(1), QRect());
+ testWindow->showNormal();
+ testWindow->widget()->hide();
+ QCOMPARE(interface->rect(1), QRect());
+ testWindow->widget()->show();
+ const QRect widgetGeometry = testWindow->contentsRect();
+ const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
+ globalPos.y() + widgetGeometry.y());
+ QCOMPARE(interface->rect(1), QRect(globalWidgetPos, widgetGeometry.size()));
+
+ // childAt
+ QCOMPARE(interface->childAt(-10, 0), -1);
+ QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0);
+ QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1);
+ testWindow->widget()->hide();
+ QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0);
+
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::lineEditTest()
+{
+ QLineEdit *le = new QLineEdit;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
+ QVERIFY(iface);
+ le->show();
+
+ QApplication::processEvents();
+ QCOMPARE(iface->childCount(), 0);
+ QVERIFY(iface->state() & QAccessible::Sizeable);
+ QVERIFY(iface->state() & QAccessible::Movable);
+ QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
+ QVERIFY(iface->state() & QAccessible::Selectable);
+ QVERIFY(iface->state() & QAccessible::HasPopup);
+ QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
+
+ QString secret(QLatin1String("secret"));
+ le->setText(secret);
+ le->setEchoMode(QLineEdit::Normal);
+ QVERIFY(!(iface->state() & QAccessible::Protected));
+ QCOMPARE(iface->text(QAccessible::Value, 0), secret);
+ le->setEchoMode(QLineEdit::NoEcho);
+ QVERIFY(iface->state() & QAccessible::Protected);
+ QVERIFY(iface->text(QAccessible::Value, 0).isEmpty());
+ le->setEchoMode(QLineEdit::Password);
+ QVERIFY(iface->state() & QAccessible::Protected);
+ QVERIFY(iface->text(QAccessible::Value, 0).isEmpty());
+ le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
+ QVERIFY(iface->state() & QAccessible::Protected);
+ QVERIFY(iface->text(QAccessible::Value, 0).isEmpty());
+ le->setEchoMode(QLineEdit::Normal);
+ QVERIFY(!(iface->state() & QAccessible::Protected));
+ QCOMPARE(iface->text(QAccessible::Value, 0), secret);
+
+ QWidget *toplevel = new QWidget;
+ le->setParent(toplevel);
+ toplevel->show();
+ QApplication::processEvents();
+ QVERIFY(!(iface->state() & QAccessible::Sizeable));
+ QVERIFY(!(iface->state() & QAccessible::Movable));
+ QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
+ QVERIFY(iface->state() & QAccessible::Selectable);
+ QVERIFY(iface->state() & QAccessible::HasPopup);
+ QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
+
+ QLineEdit *le2 = new QLineEdit(toplevel);
+ le2->show();
+ QTest::qWait(100);
+ le2->activateWindow();
+ QTest::qWait(100);
+ le->setFocus(Qt::TabFocusReason);
+ QTestAccessibility::clearEvents();
+ le2->setFocus(Qt::TabFocusReason);
+ QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
+
+ le->setText(QLatin1String("500"));
+ le->setValidator(new QIntValidator());
+ iface->setText(QAccessible::Value, 0, QLatin1String("This text is not a number"));
+ QCOMPARE(le->text(), QLatin1String("500"));
+
+ delete iface;
+ delete le;
+ delete le2;
+ QTestAccessibility::clearEvents();
+
+ // IA2
+ QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde";
+ QLineEdit *le3 = new QLineEdit(cite, toplevel);
+ iface = QAccessible::queryAccessibleInterface(le3);
+ QAccessibleTextInterface* textIface = iface->textInterface();
+ le3->deselect();
+ le3->setCursorPosition(3);
+ QCOMPARE(textIface->cursorPosition(), 3);
+ QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
+ QCOMPARE(textIface->selectionCount(), 0);
+ QTestAccessibility::clearEvents();
+
+ int start, end;
+ QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
+ QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
+ QCOMPARE(start, 0);
+ QCOMPARE(end, 1);
+ QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString());
+ QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" "));
+ QCOMPARE(start, 1);
+ QCOMPARE(end, 2);
+
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a"));
+ QCOMPARE(start, 5);
+ QCOMPARE(end, 6);
+ QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w"));
+ QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y"));
+
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
+ QCOMPARE(start, 2);
+ QCOMPARE(end, 8);
+
+ QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
+ QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
+ QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
+ QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
+ QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
+
+ QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
+ QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
+ QCOMPARE(start, 0);
+ QCOMPARE(end, 30);
+
+ QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
+ QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. "));
+
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite);
+ QCOMPARE(start, 0);
+ QCOMPARE(end, cite.length());
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
+ QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
+
+ delete iface;
+ delete toplevel;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::workspaceTest()
+{
+ {
+ QWorkspace workspace;
+ workspace.resize(400,300);
+ workspace.show();
+ const int subWindowCount = 3;
+ for (int i = 0; i < subWindowCount; ++i) {
+ QWidget *window = workspace.addWindow(new QWidget);
+ if (i > 0)
+ window->move(window->x() + 1, window->y());
+ window->show();
+ window->resize(70, window->height());
+ }
+
+ QWidgetList subWindows = workspace.windowList();
+ QCOMPARE(subWindows.count(), subWindowCount);
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), subWindowCount);
+
+ // Right, right, right, ...
+ for (int i = 0; i < subWindowCount; ++i) {
+ QAccessibleInterface *destination = 0;
+ int index = interface->navigate(QAccessible::Right, i + 1, &destination);
+ if (i == subWindowCount - 1) {
+ QVERIFY(!destination);
+ QCOMPARE(index, -1);
+ } else {
+ QVERIFY(destination);
+ QCOMPARE(index, 0);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
+ delete destination;
+ }
+ }
+
+ // Left, left, left, ...
+ for (int i = subWindowCount; i > 0; --i) {
+ QAccessibleInterface *destination = 0;
+ int index = interface->navigate(QAccessible::Left, i, &destination);
+ if (i == 1) {
+ QVERIFY(!destination);
+ QCOMPARE(index, -1);
+ } else {
+ QVERIFY(destination);
+ QCOMPARE(index, 0);
+ QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
+ delete destination;
+ }
+ }
+ // ### Add test for Up and Down.
+
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::dialogButtonBoxTest()
+{
+ {
+ QDialogButtonBox box(QDialogButtonBox::Reset |
+ QDialogButtonBox::Help |
+ QDialogButtonBox::Ok, Qt::Horizontal);
+
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
+ QVERIFY(iface);
+ box.show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+
+ QApplication::processEvents();
+ QCOMPARE(iface->childCount(), 3);
+ QCOMPARE(iface->role(), QAccessible::Grouping);
+ QCOMPARE(iface->role(1), QAccessible::PushButton);
+ QCOMPARE(iface->role(2), QAccessible::PushButton);
+ QCOMPARE(iface->role(3), QAccessible::PushButton);
+ QStringList actualOrder;
+ QAccessibleInterface *child;
+ QAccessibleInterface *leftmost;
+ child = iface->child(0);
+ // first find the leftmost button
+ while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) {
+ delete child;
+ child = leftmost;
+ }
+ leftmost = child;
+
+ // then traverse from left to right to find the correct order of the buttons
+ int right = 0;
+ while (right != -1) {
+ actualOrder << leftmost->text(QAccessible::Name, 0);
+ right = leftmost->navigate(QAccessible::Right, 1, &child);
+ delete leftmost;
+ leftmost = child;
+ }
+
+ QStringList expectedOrder;
+ QDialogButtonBox::ButtonLayout btnlout =
+ QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout));
+ switch (btnlout) {
+ case QDialogButtonBox::WinLayout:
+ expectedOrder << QDialogButtonBox::tr("Reset")
+ << QDialogButtonBox::tr("OK")
+ << QDialogButtonBox::tr("Help");
+ break;
+ case QDialogButtonBox::GnomeLayout:
+ case QDialogButtonBox::KdeLayout:
+ case QDialogButtonBox::MacLayout:
+ expectedOrder << QDialogButtonBox::tr("Help")
+ << QDialogButtonBox::tr("Reset")
+ << QDialogButtonBox::tr("OK");
+ break;
+ }
+ QCOMPARE(actualOrder, expectedOrder);
+ delete iface;
+ QApplication::processEvents();
+ QTestAccessibility::clearEvents();
+ }
+
+ {
+ QDialogButtonBox box(QDialogButtonBox::Reset |
+ QDialogButtonBox::Help |
+ QDialogButtonBox::Ok, Qt::Horizontal);
+
+
+ // Test up and down navigation
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
+ QVERIFY(iface);
+ box.setOrientation(Qt::Vertical);
+ box.show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+
+ QApplication::processEvents();
+ QAccessibleInterface *child;
+ QStringList actualOrder;
+ child = iface->child(0);
+ // first find the topmost button
+ QAccessibleInterface *other;
+ while (child->navigate(QAccessible::Up, 1, &other) != -1) {
+ delete child;
+ child = other;
+ }
+ other = child;
+
+ // then traverse from top to bottom to find the correct order of the buttons
+ actualOrder.clear();
+ int right = 0;
+ while (right != -1) {
+ actualOrder << other->text(QAccessible::Name, 0);
+ right = other->navigate(QAccessible::Down, 1, &child);
+ delete other;
+ other = child;
+ }
+
+ QStringList expectedOrder;
+ expectedOrder << QDialogButtonBox::tr("OK")
+ << QDialogButtonBox::tr("Reset")
+ << QDialogButtonBox::tr("Help");
+
+ QCOMPARE(actualOrder, expectedOrder);
+ delete iface;
+ QApplication::processEvents();
+
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::dialTest()
+{
+ {
+ QDial dial;
+ dial.setMinimum(23);
+ dial.setMaximum(121);
+ dial.setValue(42);
+ QCOMPARE(dial.value(), 42);
+ dial.show();
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 0);
+
+ QCOMPARE(interface->text(QAccessible::Value, 0), QString::number(dial.value()));
+ QCOMPARE(interface->rect(), dial.geometry());
+
+ QAccessibleValueInterface *valueIface = interface->valueInterface();
+ QVERIFY(valueIface != 0);
+ QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum());
+ QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum());
+ QCOMPARE(valueIface->currentValue().toInt(), 42);
+ dial.setValue(50);
+ QCOMPARE(valueIface->currentValue().toInt(), dial.value());
+ dial.setValue(0);
+ QCOMPARE(valueIface->currentValue().toInt(), dial.value());
+ dial.setValue(100);
+ QCOMPARE(valueIface->currentValue().toInt(), dial.value());
+ valueIface->setCurrentValue(77);
+ QCOMPARE(77, dial.value());
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::rubberBandTest()
+{
+ QRubberBand rubberBand(QRubberBand::Rectangle);
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand);
+ QVERIFY(interface);
+ QCOMPARE(interface->role(), QAccessible::Border);
+ delete interface;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::abstractScrollAreaTest()
+{
+ {
+ QAbstractScrollArea abstractScrollArea;
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
+ QVERIFY(interface);
+ QVERIFY(!interface->rect().isValid());
+ QCOMPARE(interface->childAt(200, 200), -1);
+
+ abstractScrollArea.resize(400, 400);
+ abstractScrollArea.show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+ const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)),
+ abstractScrollArea.size());
+
+ // Viewport.
+ QCOMPARE(interface->childCount(), 1);
+ QWidget *viewport = abstractScrollArea.viewport();
+ QVERIFY(viewport);
+ QVERIFY(verifyChild(viewport, interface, 1, globalGeometry));
+
+ // Horizontal scrollBar.
+ abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ QCOMPARE(interface->childCount(), 2);
+ QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar();
+ QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget();
+ QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry));
+
+ // Horizontal scrollBar widgets.
+ QLabel *secondLeftLabel = new QLabel(QLatin1String("L2"));
+ abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft);
+ QCOMPARE(interface->childCount(), 2);
+
+ QLabel *firstLeftLabel = new QLabel(QLatin1String("L1"));
+ abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft);
+ QCOMPARE(interface->childCount(), 2);
+
+ QLabel *secondRightLabel = new QLabel(QLatin1String("R2"));
+ abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight);
+ QCOMPARE(interface->childCount(), 2);
+
+ QLabel *firstRightLabel = new QLabel(QLatin1String("R1"));
+ abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight);
+ QCOMPARE(interface->childCount(), 2);
+
+ // Vertical scrollBar.
+ abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ QCOMPARE(interface->childCount(), 3);
+ QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar();
+ QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget();
+ QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry));
+
+ // Vertical scrollBar widgets.
+ QLabel *secondTopLabel = new QLabel(QLatin1String("T2"));
+ abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop);
+ QCOMPARE(interface->childCount(), 3);
+
+ QLabel *firstTopLabel = new QLabel(QLatin1String("T1"));
+ abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop);
+ QCOMPARE(interface->childCount(), 3);
+
+ QLabel *secondBottomLabel = new QLabel(QLatin1String("B2"));
+ abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom);
+ QCOMPARE(interface->childCount(), 3);
+
+ QLabel *firstBottomLabel = new QLabel(QLatin1String("B1"));
+ abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom);
+ QCOMPARE(interface->childCount(), 3);
+
+ // CornerWidget.
+ abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C")));
+ QCOMPARE(interface->childCount(), 4);
+ QWidget *cornerWidget = abstractScrollArea.cornerWidget();
+ QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry));
+
+ // Test navigate.
+ QAccessibleInterface *target = 0;
+
+ // viewport -> Up -> NOTHING
+ const int viewportIndex = indexOfChild(interface, viewport);
+ QVERIFY(viewportIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1);
+ QVERIFY(!target);
+
+ // viewport -> Left -> NOTHING
+ QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1);
+ QVERIFY(!target);
+
+ // viewport -> Down -> horizontalScrollBarContainer
+ const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer);
+ QVERIFY(horizontalScrollBarContainerIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0);
+ QVERIFY(target);
+ QCOMPARE(target->object(), static_cast<QObject *>(horizontalScrollBarContainer));
+ delete target;
+ target = 0;
+
+ // horizontalScrollBarContainer -> Left -> NOTHING
+ QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1);
+ QVERIFY(!target);
+
+ // horizontalScrollBarContainer -> Down -> NOTHING
+ QVERIFY(horizontalScrollBarContainerIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1);
+ QVERIFY(!target);
+
+ // horizontalScrollBarContainer -> Right -> cornerWidget
+ const int cornerWidgetIndex = indexOfChild(interface, cornerWidget);
+ QVERIFY(cornerWidgetIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0);
+ QVERIFY(target);
+ QCOMPARE(target->object(), static_cast<QObject *>(cornerWidget));
+ delete target;
+ target = 0;
+
+ // cornerWidget -> Down -> NOTHING
+ QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1);
+ QVERIFY(!target);
+
+ // cornerWidget -> Right -> NOTHING
+ QVERIFY(cornerWidgetIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1);
+ QVERIFY(!target);
+
+ // cornerWidget -> Up -> verticalScrollBarContainer
+ const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer);
+ QVERIFY(verticalScrollBarContainerIndex != -1);
+ QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0);
+ QVERIFY(target);
+ QCOMPARE(target->object(), static_cast<QObject *>(verticalScrollBarContainer));
+ delete target;
+ target = 0;
+
+ // verticalScrollBarContainer -> Right -> NOTHING
+ QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1);
+ QVERIFY(!target);
+
+ // verticalScrollBarContainer -> Up -> NOTHING
+ QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1);
+ QVERIFY(!target);
+
+ // verticalScrollBarContainer -> Left -> viewport
+ QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0);
+ QVERIFY(target);
+ QCOMPARE(target->object(), static_cast<QObject *>(viewport));
+ delete target;
+ target = 0;
+
+ QCOMPARE(verifyHierarchy(interface), 0);
+
+ delete interface;
+ }
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::scrollAreaTest()
+{
+ {
+ QScrollArea scrollArea;
+ scrollArea.show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea);
+ QVERIFY(interface);
+ QCOMPARE(interface->childCount(), 1); // The viewport.
+ delete interface;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+// Accessible table1 interface is no longer supported on X11,
+// where it has been replaced by table2 interface.
+#ifndef Q_OS_UNIX
+
+void tst_QAccessibility::listViewTest()
+{
+ {
+ QListView listView;
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView);
+ QVERIFY(iface);
+ QCOMPARE(iface->childCount(), 1);
+ delete iface;
+ }
+ {
+ QListWidget listView;
+ listView.addItem(tr("A"));
+ listView.addItem(tr("B"));
+ listView.addItem(tr("C"));
+ listView.resize(400,400);
+ listView.show();
+ QTest::qWait(1); // Need this for indexOfchild to work.
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&listView);
+ QCOMPARE((int)iface->role(), (int)QAccessible::Client);
+ QCOMPARE((int)iface->role(1), (int)QAccessible::List);
+ QCOMPARE(iface->childCount(), 1);
+ QAccessibleInterface *child;
+ iface->navigate(QAccessible::Child, 1, &child);
+ delete iface;
+ iface = child;
+ QCOMPARE(iface->text(QAccessible::Name, 1), QString("A"));
+ QCOMPARE(iface->text(QAccessible::Name, 2), QString("B"));
+ QCOMPARE(iface->text(QAccessible::Name, 3), QString("C"));
+
+ QCOMPARE(iface->childCount(), 3);
+
+ QAccessibleInterface *childA = 0;
+ QCOMPARE(iface->navigate(QAccessible::Child, 1, &childA), 0);
+ QVERIFY(childA);
+ QCOMPARE(iface->indexOfChild(childA), 1);
+ QCOMPARE(childA->text(QAccessible::Name, 1), QString("A"));
+ delete childA;
+
+ QAccessibleInterface *childB = 0;
+ QCOMPARE(iface->navigate(QAccessible::Child, 2, &childB), 0);
+ QVERIFY(childB);
+ QCOMPARE(iface->indexOfChild(childB), 2);
+ QCOMPARE(childB->text(QAccessible::Name, 1), QString("B"));
+ delete childB;
+
+ QAccessibleInterface *childC = 0;
+ QCOMPARE(iface->navigate(QAccessible::Child, 3, &childC), 0);
+ QVERIFY(childC);
+ QCOMPARE(iface->indexOfChild(childC), 3);
+ QCOMPARE(childC->text(QAccessible::Name, 1), QString("C"));
+ delete childC;
+ QTestAccessibility::clearEvents();
+
+ // Check for events
+ QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(1)).center());
+ QTest::mouseClick(listView.viewport(), Qt::LeftButton, 0, listView.visualItemRect(listView.item(2)).center());
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 2, QAccessible::Selection)));
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView.viewport(), 3, QAccessible::Selection)));
+ delete iface;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::treeWidgetTest()
+{
+ QWidget *w = new QWidget;
+ QTreeWidget *tree = new QTreeWidget(w);
+ QHBoxLayout *l = new QHBoxLayout(w);
+ l->addWidget(tree);
+ for (int i = 0; i < 10; ++i) {
+ QStringList strings = QStringList() << QString::fromAscii("row: %1").arg(i)
+ << QString("column 1") << QString("column 2");
+
+ tree->addTopLevelItem(new QTreeWidgetItem(strings));
+ }
+ w->show();
+
+ QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(tree);
+ QAccessibleInterface *accViewport = 0;
+ int entry = acc->navigate(QAccessible::Child, 1, &accViewport);
+ QVERIFY(accViewport);
+ QCOMPARE(entry, 0);
+ QAccessibleInterface *accTreeItem = 0;
+ entry = accViewport->navigate(QAccessible::Child, 1, &accTreeItem);
+ QCOMPARE(entry, 0);
+
+ QAccessibleInterface *accTreeItem2 = 0;
+ entry = accTreeItem->navigate(QAccessible::Sibling, 3, &accTreeItem2);
+ QCOMPARE(entry, 0);
+ QCOMPARE(accTreeItem2->text(QAccessible::Name, 0), QLatin1String("row: 1"));
+
+ // test selected/focused state
+ QItemSelectionModel *selModel = tree->selectionModel();
+ QVERIFY(selModel);
+ selModel->select(QItemSelection(tree->model()->index(0, 0), tree->model()->index(3, 0)), QItemSelectionModel::Select);
+ selModel->setCurrentIndex(tree->model()->index(1, 0), QItemSelectionModel::Current);
+
+ for (int i = 1; i < 10 ; ++i) {
+ QAccessible::State expected;
+ if (i <= 5 && i >= 2)
+ expected = QAccessible::Selected;
+ if (i == 3)
+ expected |= QAccessible::Focused;
+
+ QCOMPARE(accViewport->state(i) & (QAccessible::Focused | QAccessible::Selected), expected);
+ }
+
+ // Test sanity of its navigation functions
+ QCOMPARE(verifyHierarchy(acc), 0);
+
+ delete accTreeItem2;
+ delete accTreeItem;
+ delete accViewport;
+ delete acc;
+ delete w;
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::tableWidgetTest()
+{
+ {
+ QWidget *topLevel = new QWidget;
+ QTableWidget *w = new QTableWidget(8,4,topLevel);
+ for (int r = 0; r < 8; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ w->setItem(r, c, new QTableWidgetItem(tr("%1,%2").arg(c).arg(r)));
+ }
+ }
+ w->resize(100, 100);
+ topLevel->show();
+
+ QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w);
+ QCOMPARE(client->role(), QAccessible::Client);
+ QCOMPARE(client->childCount(), 3);
+ QAccessibleInterface *view = 0;
+ view = client->child(0);
+ QCOMPARE(view->role(), QAccessible::Table);
+ QAccessibleInterface *ifRow;
+ ifRow = view->child(1);
+ QCOMPARE(ifRow->role(), QAccessible::Row);
+ QAccessibleInterface *item;
+ int entry = ifRow->navigate(QAccessible::Child, 1, &item);
+ QCOMPARE(entry, 1);
+ QCOMPARE(item , (QAccessibleInterface*)0);
+ QCOMPARE(ifRow->text(QAccessible::Name, 2), QLatin1String("0,0"));
+ QCOMPARE(ifRow->text(QAccessible::Name, 3), QLatin1String("1,0"));
+
+ QCOMPARE(verifyHierarchy(client), 0);
+
+ delete ifRow;
+ delete view;
+ delete client;
+ delete w;
+ delete topLevel;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+class QtTestTableModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+signals:
+ void invalidIndexEncountered() const;
+
+public:
+ QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = 0)
+ : QAbstractTableModel(parent),
+ row_count(rows),
+ column_count(columns) {}
+
+ int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; }
+ int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (!idx.isValid() || idx.row() >= row_count || idx.column() >= column_count) {
+ qWarning() << "Invalid modelIndex [%d,%d,%p]" << idx;
+ emit invalidIndexEncountered();
+ return QVariant();
+ }
+
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return QString("[%1,%2,%3]").arg(idx.row()).arg(idx.column()).arg(0);
+
+ return QVariant();
+ }
+
+ void removeLastRow()
+ {
+ beginRemoveRows(QModelIndex(), row_count - 1, row_count - 1);
+ --row_count;
+ endRemoveRows();
+ }
+
+ void removeAllRows()
+ {
+ beginRemoveRows(QModelIndex(), 0, row_count - 1);
+ row_count = 0;
+ endRemoveRows();
+ }
+
+ void removeLastColumn()
+ {
+ beginRemoveColumns(QModelIndex(), column_count - 1, column_count - 1);
+ --column_count;
+ endRemoveColumns();
+ }
+
+ void removeAllColumns()
+ {
+ beginRemoveColumns(QModelIndex(), 0, column_count - 1);
+ column_count = 0;
+ endRemoveColumns();
+ }
+
+ void reset()
+ {
+ QAbstractTableModel::reset();
+ }
+
+ int row_count;
+ int column_count;
+};
+
+class QtTestDelegate : public QItemDelegate
+{
+public:
+ QtTestDelegate(QWidget *parent = 0) : QItemDelegate(parent) {}
+
+ virtual QSize sizeHint(const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const
+ {
+ return QSize(100,50);
+ }
+};
+
+void tst_QAccessibility::tableViewTest()
+{
+ {
+ QtTestTableModel *model = new QtTestTableModel(3, 4);
+ QTableView *w = new QTableView();
+ w->setModel(model);
+ w->setItemDelegate(new QtTestDelegate(w));
+ w->resize(450,200);
+ w->resizeColumnsToContents();
+ w->resizeRowsToContents();
+ w->show();
+
+ QAccessibleInterface *client = QAccessible::queryAccessibleInterface(w);
+ QAccessibleInterface *table2;
+ client->navigate(QAccessible::Child, 1, &table2);
+ QVERIFY(table2);
+ QCOMPARE(table2->role(1), QAccessible::Row);
+ QAccessibleInterface *toprow = 0;
+ table2->navigate(QAccessible::Child, 1, &toprow);
+ QVERIFY(toprow);
+ QCOMPARE(toprow->role(1), QAccessible::RowHeader);
+ QCOMPARE(toprow->role(2), QAccessible::ColumnHeader);
+ delete toprow;
+
+ // call childAt() for each child until we reach the bottom,
+ // and do it for each row in the table
+ for (int y = 1; y < 5; ++y) { // this includes the special header
+ for (int x = 1; x < 6; ++x) {
+ QCOMPARE(client->role(), QAccessible::Client);
+ QRect globalRect = client->rect();
+ QVERIFY(globalRect.isValid());
+ // make sure we don't hit the vertical header #####
+ QPoint p = globalRect.topLeft() + QPoint(8, 8);
+ p.ry() += 50 * (y - 1);
+ p.rx() += 100 * (x - 1);
+ int index = client->childAt(p.x(), p.y());
+ QCOMPARE(index, 1);
+ QCOMPARE(client->role(index), QAccessible::Table);
+
+ // navigate to table/viewport
+ QAccessibleInterface *table;
+ client->navigate(QAccessible::Child, index, &table);
+ QVERIFY(table);
+ index = table->childAt(p.x(), p.y());
+ QCOMPARE(index, y);
+ QCOMPARE(table->role(index), QAccessible::Row);
+ QAccessibleInterface *row;
+ QCOMPARE(table->role(1), QAccessible::Row);
+
+ // navigate to the row
+ table->navigate(QAccessible::Child, index, &row);
+ QVERIFY(row);
+ QCOMPARE(row->role(1), QAccessible::RowHeader);
+ index = row->childAt(p.x(), p.y());
+ QVERIFY(index > 0);
+ if (x == 1 && y == 1) {
+ QCOMPARE(row->role(index), QAccessible::RowHeader);
+ QCOMPARE(row->text(QAccessible::Name, index), QLatin1String(""));
+ } else if (x > 1 && y > 1) {
+ QCOMPARE(row->role(index), QAccessible::Cell);
+ QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("[%1,%2,0]").arg(y - 2).arg(x - 2));
+ } else if (x == 1) {
+ QCOMPARE(row->role(index), QAccessible::RowHeader);
+ QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(y - 1));
+ } else if (y == 1) {
+ QCOMPARE(row->role(index), QAccessible::ColumnHeader);
+ QCOMPARE(row->text(QAccessible::Name, index), QString::fromAscii("%1").arg(x - 1));
+ }
+ delete table;
+ delete row;
+ }
+ }
+ delete table2;
+ delete client;
+ delete w;
+ delete model;
+ }
+ QTestAccessibility::clearEvents();
+}
+
+#else
+// Test accessible table2 interface on unix
+
+void tst_QAccessibility::table2ListTest()
+{
+ QListWidget *listView = new QListWidget;
+ listView->addItem("Oslo");
+ listView->addItem("Berlin");
+ listView->addItem("Brisbane");
+ listView->resize(400,400);
+ listView->show();
+ QTest::qWait(1); // Need this for indexOfchild to work.
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView);
+ QCOMPARE(verifyHierarchy(iface), 0);
+
+ QCOMPARE((int)iface->role(), (int)QAccessible::List);
+ QCOMPARE(iface->childCount(), 3);
+
+ QAccessibleInterface *child1 = 0;
+ child1 = iface->child(0);
+ QVERIFY(child1);
+ QCOMPARE(iface->indexOfChild(child1), 1);
+ QCOMPARE(child1->text(QAccessible::Name, 0), QString("Oslo"));
+ QCOMPARE(child1->role(), QAccessible::ListItem);
+ delete child1;
+
+ QAccessibleInterface *child2 = 0;
+ child2 = iface->child(1);
+ QVERIFY(child2);
+ QCOMPARE(iface->indexOfChild(child2), 2);
+ QCOMPARE(child2->text(QAccessible::Name, 0), QString("Berlin"));
+ delete child2;
+
+ QAccessibleInterface *child3 = 0;
+ child3 = iface->child(2);
+ QVERIFY(child3);
+ QCOMPARE(iface->indexOfChild(child3), 3);
+ QCOMPARE(child3->text(QAccessible::Name, 0), QString("Brisbane"));
+ delete child3;
+ QTestAccessibility::clearEvents();
+
+ // Check for events
+ QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
+ QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
+ QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
+
+ listView->addItem("Munich");
+ QCOMPARE(iface->childCount(), 4);
+
+ // table 2
+ QAccessibleTable2Interface *table2 = iface->table2Interface();
+ QVERIFY(table2);
+ QCOMPARE(table2->columnCount(), 1);
+ QCOMPARE(table2->rowCount(), 4);
+ QAccessibleTable2CellInterface *cell1;
+ QVERIFY(cell1 = table2->cellAt(0,0));
+ QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Oslo"));
+ QAccessibleTable2CellInterface *cell4;
+ QVERIFY(cell4 = table2->cellAt(3,0));
+ QCOMPARE(cell4->text(QAccessible::Name, 0), QString("Munich"));
+ QCOMPARE(cell4->role(), QAccessible::ListItem);
+ QCOMPARE(cell4->rowIndex(), 3);
+ QCOMPARE(cell4->columnIndex(), 0);
+ QVERIFY(!cell4->isExpandable());
+
+ delete cell4;
+ delete cell1;
+ delete iface;
+ delete listView;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::table2TreeTest()
+{
+ QTreeWidget *treeView = new QTreeWidget;
+ treeView->setColumnCount(2);
+ QTreeWidgetItem *header = new QTreeWidgetItem;
+ header->setText(0, "Artist");
+ header->setText(1, "Work");
+ treeView->setHeaderItem(header);
+
+ QTreeWidgetItem *root1 = new QTreeWidgetItem;
+ root1->setText(0, "Spain");
+ treeView->addTopLevelItem(root1);
+
+ QTreeWidgetItem *item1 = new QTreeWidgetItem;
+ item1->setText(0, "Picasso");
+ item1->setText(1, "Guernica");
+ root1->addChild(item1);
+
+ QTreeWidgetItem *item2 = new QTreeWidgetItem;
+ item2->setText(0, "Tapies");
+ item2->setText(1, "Ambrosia");
+ root1->addChild(item2);
+
+ QTreeWidgetItem *root2 = new QTreeWidgetItem;
+ root2->setText(0, "Austria");
+ treeView->addTopLevelItem(root2);
+
+ QTreeWidgetItem *item3 = new QTreeWidgetItem;
+ item3->setText(0, "Klimt");
+ item3->setText(1, "The Kiss");
+ root2->addChild(item3);
+
+ treeView->resize(400,400);
+ treeView->show();
+
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
+ QCOMPARE(verifyHierarchy(iface), 0);
+
+ QCOMPARE((int)iface->role(), (int)QAccessible::Tree);
+ // header and 2 rows (the others are not expanded, thus not visible)
+ QCOMPARE(iface->childCount(), 6);
+
+ QAccessibleInterface *header1 = 0;
+ header1 = iface->child(0);
+ QVERIFY(header1);
+ QCOMPARE(iface->indexOfChild(header1), 1);
+ QCOMPARE(header1->text(QAccessible::Name, 0), QString("Artist"));
+ QCOMPARE(header1->role(), QAccessible::ColumnHeader);
+ delete header1;
+
+ QAccessibleInterface *child1 = 0;
+ child1 = iface->child(2);
+ QVERIFY(child1);
+ QCOMPARE(iface->indexOfChild(child1), 3);
+ QCOMPARE(child1->text(QAccessible::Name, 0), QString("Spain"));
+ QCOMPARE(child1->role(), QAccessible::TreeItem);
+ QVERIFY(!(child1->state() & QAccessible::Expanded));
+ delete child1;
+
+ QAccessibleInterface *child2 = 0;
+ child2 = iface->child(4);
+ QVERIFY(child2);
+ QCOMPARE(iface->indexOfChild(child2), 5);
+ QCOMPARE(child2->text(QAccessible::Name, 0), QString("Austria"));
+ delete child2;
+
+ QTestAccessibility::clearEvents();
+
+ // table 2
+ QAccessibleTable2Interface *table2 = iface->table2Interface();
+ QVERIFY(table2);
+ QCOMPARE(table2->columnCount(), 2);
+ QCOMPARE(table2->rowCount(), 2);
+ QAccessibleTable2CellInterface *cell1;
+ QVERIFY(cell1 = table2->cellAt(0,0));
+ QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Spain"));
+ QAccessibleTable2CellInterface *cell2;
+ QVERIFY(cell2 = table2->cellAt(1,0));
+ QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Austria"));
+ QCOMPARE(cell2->role(), QAccessible::TreeItem);
+ QCOMPARE(cell2->rowIndex(), 1);
+ QCOMPARE(cell2->columnIndex(), 0);
+ QVERIFY(cell2->isExpandable());
+ QCOMPARE(iface->indexOfChild(cell2), 5);
+ QVERIFY(!(cell2->state() & QAccessible::Expanded));
+ QCOMPARE(table2->columnDescription(1), QString("Work"));
+ delete cell2;
+ delete cell1;
+
+ treeView->expandAll();
+
+ // Need this for indexOfchild to work.
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ QCOMPARE(table2->columnCount(), 2);
+ QCOMPARE(table2->rowCount(), 5);
+ cell1 = table2->cellAt(1,0);
+ QCOMPARE(cell1->text(QAccessible::Name, 0), QString("Picasso"));
+ QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
+
+ cell2 = table2->cellAt(4,0);
+ QCOMPARE(cell2->text(QAccessible::Name, 0), QString("Klimt"));
+ QCOMPARE(cell2->role(), QAccessible::TreeItem);
+ QCOMPARE(cell2->rowIndex(), 4);
+ QCOMPARE(cell2->columnIndex(), 0);
+ QVERIFY(!cell2->isExpandable());
+ QCOMPARE(iface->indexOfChild(cell2), 11);
+
+ QCOMPARE(table2->columnDescription(0), QString("Artist"));
+ QCOMPARE(table2->columnDescription(1), QString("Work"));
+
+ delete iface;
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::table2TableTest()
+{
+ QTableWidget *tableView = new QTableWidget(3, 3);
+ tableView->setColumnCount(3);
+ QStringList hHeader;
+ hHeader << "h1" << "h2" << "h3";
+ tableView->setHorizontalHeaderLabels(hHeader);
+
+ QStringList vHeader;
+ vHeader << "v1" << "v2" << "v3";
+ tableView->setVerticalHeaderLabels(vHeader);
+
+ for (int i = 0; i<9; ++i) {
+ QTableWidgetItem *item = new QTableWidgetItem;
+ item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
+ tableView->setItem(i/3, i%3, item);
+ }
+
+ tableView->resize(600,600);
+ tableView->show();
+ QTest::qWait(1); // Need this for indexOfchild to work.
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
+ QCOMPARE(verifyHierarchy(iface), 0);
+
+ QCOMPARE((int)iface->role(), (int)QAccessible::Table);
+ // header and 2 rows (the others are not expanded, thus not visible)
+ QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
+
+ QAccessibleInterface *cornerButton = iface->child(0);
+ QVERIFY(cornerButton);
+ QCOMPARE(iface->indexOfChild(cornerButton), 1);
+ QCOMPARE(cornerButton->role(), QAccessible::Pane);
+ delete cornerButton;
+
+ QAccessibleInterface *child1 = iface->child(2);
+ QVERIFY(child1);
+ QCOMPARE(iface->indexOfChild(child1), 3);
+ QCOMPARE(child1->text(QAccessible::Name, 0), QString("h2"));
+ QCOMPARE(child1->role(), QAccessible::ColumnHeader);
+ QVERIFY(!(child1->state() & QAccessible::Expanded));
+ delete child1;
+
+ QAccessibleInterface *child2 = iface->child(10);
+ QVERIFY(child2);
+ QCOMPARE(iface->indexOfChild(child2), 11);
+ QCOMPARE(child2->text(QAccessible::Name, 0), QString("1.1"));
+ QAccessibleTable2CellInterface *cell2Iface = static_cast<QAccessibleTable2CellInterface*>(child2);
+ QCOMPARE(cell2Iface->rowIndex(), 1);
+ QCOMPARE(cell2Iface->columnIndex(), 1);
+ delete child2;
+
+ QAccessibleInterface *child3 = iface->child(11);
+ QCOMPARE(iface->indexOfChild(child3), 12);
+ QCOMPARE(child3->text(QAccessible::Name, 0), QString("1.2"));
+ delete child3;
+
+ QTestAccessibility::clearEvents();
+
+ // table 2
+ QAccessibleTable2Interface *table2 = iface->table2Interface();
+ QVERIFY(table2);
+ QCOMPARE(table2->columnCount(), 3);
+ QCOMPARE(table2->rowCount(), 3);
+ QAccessibleTable2CellInterface *cell1;
+ QVERIFY(cell1 = table2->cellAt(0,0));
+ QCOMPARE(cell1->text(QAccessible::Name, 0), QString("0.0"));
+ QCOMPARE(iface->indexOfChild(cell1), 6);
+
+ QAccessibleTable2CellInterface *cell2;
+ QVERIFY(cell2 = table2->cellAt(0,1));
+ QCOMPARE(cell2->text(QAccessible::Name, 0), QString("0.1"));
+ QCOMPARE(cell2->role(), QAccessible::Cell);
+ QCOMPARE(cell2->rowIndex(), 0);
+ QCOMPARE(cell2->columnIndex(), 1);
+ QCOMPARE(iface->indexOfChild(cell2), 7);
+ delete cell2;
+
+ QAccessibleTable2CellInterface *cell3;
+ QVERIFY(cell3 = table2->cellAt(1,2));
+ QCOMPARE(cell3->text(QAccessible::Name, 0), QString("1.2"));
+ QCOMPARE(cell3->role(), QAccessible::Cell);
+ QCOMPARE(cell3->rowIndex(), 1);
+ QCOMPARE(cell3->columnIndex(), 2);
+ QCOMPARE(iface->indexOfChild(cell3), 12);
+ delete cell3;
+
+ QCOMPARE(table2->columnDescription(0), QString("h1"));
+ QCOMPARE(table2->columnDescription(1), QString("h2"));
+ QCOMPARE(table2->columnDescription(2), QString("h3"));
+ QCOMPARE(table2->rowDescription(0), QString("v1"));
+ QCOMPARE(table2->rowDescription(1), QString("v2"));
+ QCOMPARE(table2->rowDescription(2), QString("v3"));
+
+ delete iface;
+
+ delete tableView;
+
+ QTestAccessibility::clearEvents();
+}
+#endif
+
+void tst_QAccessibility::calendarWidgetTest()
+{
+#ifndef QT_NO_CALENDARWIDGET
+ {
+ QCalendarWidget calendarWidget;
+
+ QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget);
+ QVERIFY(interface);
+ QCOMPARE(interface->role(), QAccessible::Table);
+ QVERIFY(!interface->rect().isValid());
+ QVERIFY(!interface->rect(1).isValid());
+ QCOMPARE(interface->childAt(200, 200), -1);
+
+ calendarWidget.resize(400, 300);
+ calendarWidget.show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+
+ // 1 = navigationBar, 2 = view.
+ QCOMPARE(interface->childCount(), 2);
+
+ const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)),
+ calendarWidget.size());
+ QCOMPARE(interface->rect(), globalGeometry);
+
+ QWidget *navigationBar = 0;
+ foreach (QObject *child, calendarWidget.children()) {
+ if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) {
+ navigationBar = static_cast<QWidget *>(child);
+ break;
+ }
+ }
+ QVERIFY(navigationBar);
+ QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry));
+
+ QAbstractItemView *calendarView = 0;
+ foreach (QObject *child, calendarWidget.children()) {
+ if (child->objectName() == QLatin1String("qt_calendar_calendarview")) {
+ calendarView = static_cast<QAbstractItemView *>(child);
+ break;
+ }
+ }
+ QVERIFY(calendarView);
+ QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry));
+
+ // Hide navigation bar.
+ calendarWidget.setNavigationBarVisible(false);
+ QCOMPARE(interface->childCount(), 1);
+ QVERIFY(!navigationBar->isVisible());
+
+ QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry));
+
+ // Show navigation bar.
+ calendarWidget.setNavigationBarVisible(true);
+ QCOMPARE(interface->childCount(), 2);
+ QVERIFY(navigationBar->isVisible());
+
+ // Navigate to the navigation bar via Child.
+ QAccessibleInterface *navigationBarInterface = interface->child(0);
+ QVERIFY(navigationBarInterface);
+ QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
+ delete navigationBarInterface;
+ navigationBarInterface = 0;
+
+ // Navigate to the view via Child.
+ QAccessibleInterface *calendarViewInterface = interface->child(1);
+ QVERIFY(calendarViewInterface);
+ QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
+ delete calendarViewInterface;
+ calendarViewInterface = 0;
+
+ QVERIFY(!interface->child(-1));
+
+ // Navigate from navigation bar -> view (Down).
+ QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0);
+ QVERIFY(calendarViewInterface);
+ QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
+ delete calendarViewInterface;
+ calendarViewInterface = 0;
+
+ // Navigate from view -> navigation bar (Up).
+ QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0);
+ QVERIFY(navigationBarInterface);
+ QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
+ delete navigationBarInterface;
+ navigationBarInterface = 0;
+
+ }
+ QTestAccessibility::clearEvents();
+#endif // QT_NO_CALENDARWIDGET
+}
+
+void tst_QAccessibility::dockWidgetTest()
+{
+#ifndef QT_NO_DOCKWIDGET
+ // Set up a proper main window with two dock widgets
+ QMainWindow *mw = new QMainWindow();
+ QFrame *central = new QFrame(mw);
+ mw->setCentralWidget(central);
+ QMenuBar *mb = new QMenuBar(mw);
+ mb->addAction(tr("&File"));
+ mw->setMenuBar(mb);
+
+ QDockWidget *dock1 = new QDockWidget(mw);
+ mw->addDockWidget(Qt::LeftDockWidgetArea, dock1);
+ QPushButton *pb1 = new QPushButton(tr("Push me"), dock1);
+ dock1->setWidget(pb1);
+
+ QDockWidget *dock2 = new QDockWidget(mw);
+ mw->addDockWidget(Qt::BottomDockWidgetArea, dock2);
+ QPushButton *pb2 = new QPushButton(tr("Push me"), dock2);
+ dock2->setWidget(pb2);
+
+ mw->resize(600,400);
+ mw->show();
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+ QTest::qWait(100);
+#endif
+
+ QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw);
+ // 4 children: menu bar, dock1, dock2, and central widget
+ QCOMPARE(accMainWindow->childCount(), 4);
+ QAccessibleInterface *accDock1 = 0;
+ for (int i = 1; i <= 4; ++i) {
+ if (accMainWindow->role(i) == QAccessible::Window) {
+ accDock1 = accMainWindow->child(i-1);
+ if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) {
+ break;
+ } else {
+ delete accDock1;
+ }
+ }
+ }
+ QVERIFY(accDock1);
+ QCOMPARE(accDock1->role(), QAccessible::Window);
+ QCOMPARE(accDock1->role(1), QAccessible::TitleBar);
+ QVERIFY(accDock1->rect().contains(accDock1->rect(1)));
+
+ QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
+ globalPos.rx()+=5; //### query style
+ globalPos.ry()+=5;
+ int entry = accDock1->childAt(globalPos.x(), globalPos.y()); //###
+ QCOMPARE(entry, 1);
+ QAccessibleInterface *accTitleBar = accDock1->child(entry - 1);
+
+ QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
+ QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);
+ QAccessibleInterface *acc;
+ acc = accTitleBar->parent();
+ QVERIFY(acc);
+ QCOMPARE(acc->role(), QAccessible::Window);
+
+
+ delete accTitleBar;
+ delete accDock1;
+ delete pb1;
+ delete pb2;
+ delete dock1;
+ delete dock2;
+ delete mw;
+ QTestAccessibility::clearEvents();
+#endif // QT_NO_DOCKWIDGET
+}
+
+void tst_QAccessibility::comboBoxTest()
+{
+#if defined(Q_OS_WINCE)
+ if (!IsValidCEPlatform()) {
+ QSKIP("Test skipped on Windows Mobile test hardware", SkipAll);
+ }
+#endif
+ { // not editable combobox
+ QComboBox combo;
+ combo.addItems(QStringList() << "one" << "two" << "three");
+ combo.show();
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
+ QCOMPARE(verifyHierarchy(iface), 0);
+
+ QCOMPARE(iface->role(), QAccessible::ComboBox);
+ QCOMPARE(iface->childCount(), 1);
+
+#ifdef Q_OS_UNIX
+ QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one"));
+#endif
+ QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one"));
+ combo.setCurrentIndex(2);
+#ifdef Q_OS_UNIX
+ QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three"));
+#endif
+ QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three"));
+
+ QAccessibleInterface *listIface = iface->child(0);
+ QCOMPARE(listIface->role(), QAccessible::List);
+ QCOMPARE(listIface->childCount(), 3);
+
+ QVERIFY(!combo.view()->isVisible());
+ QVERIFY(iface->actionInterface());
+ QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::ShowMenuAction);
+ iface->actionInterface()->doAction(QAccessibleActionInterface::ShowMenuAction);
+ QVERIFY(combo.view()->isVisible());
+
+ delete iface;
+ }
+
+ { // editable combobox
+ QComboBox editableCombo;
+ editableCombo.show();
+ editableCombo.setEditable(true);
+ editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo);
+ QCOMPARE(verifyHierarchy(iface), 0);
+
+ QCOMPARE(iface->role(), QAccessible::ComboBox);
+ QCOMPARE(iface->childCount(), 2);
+
+ QAccessibleInterface *listIface = iface->child(0);
+ QCOMPARE(listIface->role(), QAccessible::List);
+ QAccessibleInterface *editIface = iface->child(1);
+ QCOMPARE(editIface->role(), QAccessible::EditableText);
+
+ delete listIface;
+ delete editIface;
+ delete iface;
+ }
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::labelTest()
+{
+ QString text = "Hello World";
+ QLabel *label = new QLabel(text);
+ label->show();
+
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+#endif
+ QTest::qWait(100);
+
+ QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label);
+ QVERIFY(acc_label);
+
+ QCOMPARE(acc_label->text(QAccessible::Name, 0), text);
+
+ delete acc_label;
+ delete label;
+ QTestAccessibility::clearEvents();
+
+ QPixmap testPixmap(50, 50);
+ testPixmap.fill();
+
+ QLabel imageLabel;
+ imageLabel.setPixmap(testPixmap);
+ imageLabel.setToolTip("Test Description");
+
+ acc_label = QAccessible::queryAccessibleInterface(&imageLabel);
+ QVERIFY(acc_label);
+
+ QAccessibleImageInterface *imageInterface = acc_label->imageInterface();
+ QVERIFY(imageInterface);
+
+ QCOMPARE(imageInterface->imageSize(), testPixmap.size());
+ QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
+ QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
+
+ delete acc_label;
+
+ QTestAccessibility::clearEvents();
+}
+
+void tst_QAccessibility::accelerators()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay = new QHBoxLayout(window);
+ QLabel *label = new QLabel(tr("&Line edit"), window);
+ QLineEdit *le = new QLineEdit(window);
+ lay->addWidget(label);
+ lay->addWidget(le);
+ label->setBuddy(le);
+
+ window->show();
+
+ QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
+ label->setText(tr("Q &"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
+ label->setText(tr("Q &&"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
+ label->setText(tr("Q && A"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
+ label->setText(tr("Q &&&A"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
+ label->setText(tr("Q &&A"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
+
+#if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC)
+ QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'");
+#endif
+ label->setText(tr("Q &A&B"));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
+
+#if defined(Q_OS_UNIX)
+ QCoreApplication::processEvents();
+#endif
+ QTest::qWait(100);
+ delete window;
+ QTestAccessibility::clearEvents();
+}
+
+QTEST_MAIN(tst_QAccessibility)
+#include "tst_qaccessibility.moc"