1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
48 #if defined(Q_OS_WIN) && defined(interface)
53 #include "QtTest/qtestaccessible.h"
55 #if defined(Q_OS_WINCE)
56 extern "C" bool SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
57 #define SPI_GETPLATFORMTYPE 257
58 inline bool IsValidCEPlatform() {
59 wchar_t tszPlatform[64];
60 if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(*tszPlatform), tszPlatform, 0)) {
61 QString platform = QString::fromWCharArray(tszPlatform);
62 if ((platform == QLatin1String("PocketPC")) || (platform == QLatin1String("Smartphone")))
69 static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
70 int index, const QRect &domain)
73 qWarning("tst_QAccessibility::verifyChild: null pointer to child.");
78 qWarning("tst_QAccessibility::verifyChild: null pointer to interface.");
82 // Verify that we get a valid QAccessibleInterface for the child.
83 QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child);
84 if (!childInterface) {
85 qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child.");
89 // QAccessibleInterface::indexOfChild():
90 // Verify that indexOfChild() returns an index equal to the index passed in
91 int indexFromIndexOfChild = interface->indexOfChild(childInterface);
92 if (indexFromIndexOfChild != index) {
93 qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
94 qWarning() << "Expected:" << index;
95 qWarning() << "Actual: " << indexFromIndexOfChild;
99 // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child).
100 QAccessibleInterface *navigatedChildInterface = interface->child(index - 1);
101 if (navigatedChildInterface == 0)
104 const QRect rectFromInterface = navigatedChildInterface->rect();
105 delete navigatedChildInterface;
107 // QAccessibleInterface::childAt():
108 // Calculate global child position and check that the interface
109 // returns the correct index for that position.
110 QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
111 QAccessibleInterface *childAtInterface = interface->childAt(globalChildPos.x(), globalChildPos.y());
112 if (!childAtInterface) {
113 qWarning("tst_QAccessibility::verifyChild (childAt()):");
114 qWarning() << "Expected:" << childInterface;
115 qWarning() << "Actual: no child";
118 if (childAtInterface->object() != childInterface->object()) {
119 qWarning("tst_QAccessibility::verifyChild (childAt()):");
120 qWarning() << "Expected:" << childInterface;
121 qWarning() << "Actual: " << childAtInterface;
124 delete childInterface;
125 delete childAtInterface;
127 // QAccessibleInterface::rect():
128 // Calculate global child geometry and check that the interface
129 // returns a QRect which is equal to the calculated QRect.
130 const QRect expectedGlobalRect = QRect(globalChildPos, child->size());
131 if (expectedGlobalRect != rectFromInterface) {
132 qWarning("tst_QAccessibility::verifyChild (rect()):");
133 qWarning() << "Expected:" << expectedGlobalRect;
134 qWarning() << "Actual: " << rectFromInterface;
138 // Verify that the child is within its domain.
139 if (!domain.contains(rectFromInterface)) {
140 qWarning("tst_QAccessibility::verifyChild: Child is not within its domain.");
147 static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget)
149 if (!parentInterface || !childWidget)
151 QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(childWidget);
154 int index = parentInterface->indexOfChild(childInterface);
155 delete childInterface;
159 #define EXPECT(cond) \
161 if (!errorAt && !(cond)) { \
162 errorAt = __LINE__; \
163 qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
167 static int verifyHierarchy(QAccessibleInterface *iface)
170 static int treelevel = 0; // for error diagnostics
171 QAccessibleInterface *middleChild, *if2;
174 int middle = iface->childCount()/2 + 1;
175 if (iface->childCount() >= 2) {
176 middleChild = iface->child(middle - 1);
178 for (int i = 0; i < iface->childCount() && !errorAt; ++i) {
179 if2 = iface->child(i);
181 // navigate Ancestor...
182 QAccessibleInterface *parent = if2->parent();
183 EXPECT(iface->object() == parent->object());
186 // navigate Sibling...
187 // if (middleChild) {
188 // entry = if2->navigate(QAccessible::Sibling, middle, &if3);
189 // EXPECT(entry == 0 && if3->object() == middleChild->object());
192 // EXPECT(iface->indexOfChild(middleChild) == middle);
195 // verify children...
197 errorAt = verifyHierarchy(if2);
206 QRect childRect(QAccessibleInterface *iface, int index = 0)
208 QAccessibleInterface *child = iface->child(index);
209 QRect rect = child->rect();
214 class tst_QAccessibility : public QObject
218 tst_QAccessibility();
219 virtual ~tst_QAccessibility();
223 void cleanupTestCase();
229 void deletedWidget();
231 void navigateGeometric();
232 void navigateHierarchy();
234 void navigateCovered();
235 void textAttributes();
240 void applicationTest();
241 void mainWindowTest();
243 void scrollBarTest();
245 void tabWidgetTest();
248 void doubleSpinBoxTest();
250 void textBrowserTest();
252 void mdiSubWindowTest();
254 void workspaceTest();
255 void dialogButtonBoxTest();
257 void rubberBandTest();
258 void abstractScrollAreaTest();
259 void scrollAreaTest();
265 void calendarWidgetTest();
266 void dockWidgetTest();
268 void accessibleName();
278 const double Q_PI = 3.14159265358979323846;
280 QString eventName(const int ev)
283 case 0x0001: return "SoundPlayed";
284 case 0x0002: return "Alert";
285 case 0x0003: return "ForegroundChanged";
286 case 0x0004: return "MenuStart";
287 case 0x0005: return "MenuEnd";
288 case 0x0006: return "PopupMenuStart";
289 case 0x0007: return "PopupMenuEnd";
290 case 0x000C: return "ContextHelpStart";
291 case 0x000D: return "ContextHelpEnd";
292 case 0x000E: return "DragDropStart";
293 case 0x000F: return "DragDropEnd";
294 case 0x0010: return "DialogStart";
295 case 0x0011: return "DialogEnd";
296 case 0x0012: return "ScrollingStart";
297 case 0x0013: return "ScrollingEnd";
298 case 0x0018: return "MenuCommand";
300 case 0x0116: return "TableModelChanged";
301 case 0x011B: return "TextCaretMoved";
303 case 0x8000: return "ObjectCreated";
304 case 0x8001: return "ObjectDestroyed";
305 case 0x8002: return "ObjectShow";
306 case 0x8003: return "ObjectHide";
307 case 0x8004: return "ObjectReorder";
308 case 0x8005: return "Focus";
309 case 0x8006: return "Selection";
310 case 0x8007: return "SelectionAdd";
311 case 0x8008: return "SelectionRemove";
312 case 0x8009: return "SelectionWithin";
313 case 0x800A: return "StateChanged";
314 case 0x800B: return "LocationChanged";
315 case 0x800C: return "NameChanged";
316 case 0x800D: return "DescriptionChanged";
317 case 0x800E: return "ValueChanged";
318 case 0x800F: return "ParentChanged";
319 case 0x80A0: return "HelpChanged";
320 case 0x80B0: return "DefaultActionChanged";
321 case 0x80C0: return "AcceleratorChanged";
322 default: return "Unknown Event";
326 QAccessible::State state(QWidget * const widget)
328 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
330 qWarning() << "Cannot get QAccessibleInterface for widget";
331 QAccessible::State state = (iface ? iface->state() : static_cast<QAccessible::State>(0));
336 class QtTestAccessibleWidget: public QWidget
340 QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
344 pal.setColor(backgroundRole(), Qt::black);//black is beautiful
350 class QtTestAccessibleWidgetIface: public QAccessibleWidget
353 QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
354 QString text(QAccessible::Text t) const
356 if (t == QAccessible::Help)
357 return QString::fromLatin1("Help yourself");
358 return QAccessibleWidget::text(t);
360 static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
362 if (key == "QtTestAccessibleWidget")
363 return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
368 tst_QAccessibility::tst_QAccessibility()
373 tst_QAccessibility::~tst_QAccessibility()
377 void tst_QAccessibility::onClicked()
382 void tst_QAccessibility::initTestCase()
384 QTestAccessibility::initialize();
385 QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
388 void tst_QAccessibility::cleanupTestCase()
390 QTestAccessibility::cleanup();
393 void tst_QAccessibility::init()
395 QTestAccessibility::clearEvents();
398 void tst_QAccessibility::cleanup()
400 const EventList list = QTestAccessibility::events();
401 if (!list.isEmpty()) {
402 qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
403 QString(QTest::currentTestFunction()).toAscii().constData());
404 for (int i = 0; i < list.count(); ++i)
405 qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
406 eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
408 QTestAccessibility::clearEvents();
411 void tst_QAccessibility::eventTest()
413 QPushButton* button = new QPushButton(0);
414 button->setObjectName(QString("Olaf"));
417 QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
418 button->setFocus(Qt::MouseFocusReason);
419 QTestAccessibility::clearEvents();
420 QTest::mouseClick(button, Qt::LeftButton, 0);
421 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
422 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
424 button->setAccessibleName("Olaf the second");
425 QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
426 button->setAccessibleDescription("This is a button labeled Olaf");
427 QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
430 QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
435 void tst_QAccessibility::customWidget()
437 QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
439 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
441 QVERIFY(iface->isValid());
442 QCOMPARE(iface->object(), (QObject*)widget);
443 QCOMPARE(iface->object()->objectName(), QString("Heinz"));
444 QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
450 void tst_QAccessibility::deletedWidget()
452 QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
453 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
455 QVERIFY(iface->isValid());
456 QCOMPARE(iface->object(), (QObject*)widget);
460 QVERIFY(!iface->isValid());
464 void tst_QAccessibility::navigateGeometric()
467 static const int skip = 20; //speed the test up significantly
468 static const double step = Q_PI / 180;
469 QWidget *w = new QWidget(0);
470 w->setObjectName(QString("Josef"));
471 w->setFixedSize(400, 400);
474 QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol");
475 center->move(200, 200);
477 // arrange 360 widgets around it in a circle
478 QtTestAccessibleWidget *aw = 0;
479 for (int i = 0; i < 360; i += skip) {
480 aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1());
481 aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) );
484 aw = new QtTestAccessibleWidget(w, "Earth");
485 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center);
486 QAccessibleInterface *target = 0;
488 QVERIFY(iface->isValid());
491 QCoreApplication::processEvents();
494 // let one widget rotate around center
495 for (int i = 0; i < 360; i+=skip) {
496 aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) );
498 if (i < 45 || i > 315) {
499 QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
500 } else if ( i < 135 ) {
501 QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
502 } else if ( i < 225 ) {
503 QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
505 QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
509 QVERIFY(target->isValid());
510 QVERIFY(target->object());
511 QCOMPARE(target->object()->objectName(), aw->objectName());
512 delete target; target = 0;
515 // test invisible widget
516 target = QAccessible::queryAccessibleInterface(aw);
517 QVERIFY(!(target->state() & QAccessible::Invisible));
519 QVERIFY(target->state() & QAccessible::Invisible);
520 delete target; target = 0;
522 aw->move(center->x() + 10, center->y());
523 QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
525 QVERIFY(target->isValid());
526 QVERIFY(target->object());
527 QVERIFY(QString(target->object()->objectName()) != "Earth");
528 delete target; target = 0;
530 aw->move(center->x() - 10, center->y());
531 QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
533 QVERIFY(target->isValid());
534 QVERIFY(target->object());
535 QVERIFY(QString(target->object()->objectName()) != "Earth");
536 delete target; target = 0;
538 aw->move(center->x(), center->y() + 10);
539 QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
541 QVERIFY(target->isValid());
542 QVERIFY(target->object());
543 QVERIFY(QString(target->object()->objectName()) != "Earth");
544 delete target; target = 0;
546 aw->move(center->x(), center->y() - 10);
547 QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
549 QVERIFY(target->isValid());
550 QVERIFY(target->object());
551 QVERIFY(QString(target->object()->objectName()) != "Earth");
552 delete target; target = 0;
557 QTestAccessibility::clearEvents();
560 void tst_QAccessibility::sliderTest()
563 QSlider *slider = new QSlider(0);
564 slider->setObjectName(QString("Slidy"));
566 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider);
568 QVERIFY(iface->isValid());
570 QCOMPARE(iface->childCount(), 0);
571 QCOMPARE(iface->role(), QAccessible::Slider);
573 QAccessibleValueInterface *valueIface = iface->valueInterface();
574 QVERIFY(valueIface != 0);
575 QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum());
576 QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum());
577 slider->setValue(50);
578 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
580 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
581 slider->setValue(100);
582 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
583 valueIface->setCurrentValue(77);
584 QCOMPARE(77, slider->value());
589 QTestAccessibility::clearEvents();
592 void tst_QAccessibility::navigateCovered()
595 QWidget *w = new QWidget(0);
596 w->setObjectName(QString("Harry"));
597 QWidget *w1 = new QWidget(w);
598 w1->setObjectName(QString("1"));
599 QWidget *w2 = new QWidget(w);
600 w2->setObjectName(QString("2"));
602 #if defined(Q_OS_UNIX)
603 QCoreApplication::processEvents();
607 w->setFixedSize(6, 6);
608 w1->setFixedSize(5, 5);
609 w2->setFixedSize(5, 5);
613 QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1);
614 QVERIFY(iface1 != 0);
615 QVERIFY(iface1->isValid());
616 QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2);
617 QVERIFY(iface2 != 0);
618 QVERIFY(iface2->isValid());
619 QAccessibleInterface *iface3 = 0;
621 QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1);
622 QVERIFY(iface3 == 0);
623 QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1);
624 QVERIFY(iface3 == 0);
625 QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1);
626 QVERIFY(iface3 == 0);
628 for (int loop = 0; loop < 2; ++loop) {
629 for (int x = 0; x < w->width(); ++x) {
630 for (int y = 0; y < w->height(); ++y) {
632 if (w1->geometry().intersects(w2->geometry())) {
633 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
634 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
635 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0);
636 QVERIFY(iface3 != 0);
637 QVERIFY(iface3->isValid());
638 QCOMPARE(iface3->object(), iface2->object());
639 delete iface3; iface3 = 0;
640 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0);
641 QVERIFY(iface3 != 0);
642 QVERIFY(iface3->isValid());
643 QCOMPARE(iface3->object(), iface1->object());
644 delete iface3; iface3 = 0;
646 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
647 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
648 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1);
649 QVERIFY(iface3 == 0);
650 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
651 QVERIFY(iface3 == 0);
652 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
653 QVERIFY(iface3 == 0);
654 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1);
655 QVERIFY(iface3 == 0);
660 // switch children for second loop
662 QAccessibleInterface *temp = iface1;
667 delete iface1; iface1 = 0;
668 delete iface2; iface2 = 0;
669 iface1 = QAccessible::queryAccessibleInterface(w1);
670 QVERIFY(iface1 != 0);
671 QVERIFY(iface1->isValid());
672 iface2 = QAccessible::queryAccessibleInterface(w2);
673 QVERIFY(iface2 != 0);
674 QVERIFY(iface2->isValid());
679 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
680 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
681 QVERIFY(!(iface1->state() & QAccessible::Invisible));
683 QVERIFY(iface1->state() & QAccessible::Invisible);
684 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
685 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
686 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
687 QVERIFY(iface3 == 0);
688 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
689 QVERIFY(iface3 == 0);
691 delete iface1; iface1 = 0;
692 delete iface2; iface2 = 0;
695 QTestAccessibility::clearEvents();
698 void tst_QAccessibility::navigateHierarchy()
701 QWidget *w = new QWidget(0);
702 w->setObjectName(QString("Hans"));
704 QWidget *w1 = new QWidget(w);
705 w1->setObjectName(QString("1"));
707 QWidget *w2 = new QWidget(w);
708 w2->setObjectName(QString("2"));
710 QWidget *w3 = new QWidget(w);
711 w3->setObjectName(QString("3"));
713 QWidget *w31 = new QWidget(w3);
714 w31->setObjectName(QString("31"));
717 QAccessibleInterface *target = 0;
718 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w);
720 QVERIFY(iface->isValid());
722 QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1);
723 QVERIFY(target == 0);
724 QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1);
725 QVERIFY(target == 0);
727 target = iface->child(14);
728 QVERIFY(target == 0);
729 target = iface->child(-1);
730 QVERIFY(target == 0);
731 target = iface->child(0);
732 QAccessibleInterface *interfaceW1 = iface->child(0);
734 QVERIFY(target->isValid());
735 QCOMPARE(target->object(), (QObject*)w1);
736 QVERIFY(interfaceW1 != 0);
737 QVERIFY(interfaceW1->isValid());
738 QCOMPARE(interfaceW1->object(), (QObject*)w1);
740 delete iface; iface = 0;
742 QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1);
744 QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1);
746 QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1);
748 QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0);
750 QVERIFY(iface->isValid());
751 QCOMPARE(iface->object(), (QObject*)w2);
752 delete target; target = 0;
753 QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0);
754 QVERIFY(target != 0);
755 QVERIFY(target->isValid());
756 QCOMPARE(target->object(), (QObject*)w3);
757 delete iface; iface = 0;
759 iface = target->child(0);
761 QVERIFY(iface->isValid());
762 QCOMPARE(iface->object(), (QObject*)w31);
763 delete target; target = 0;
765 QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1);
766 QVERIFY(target == 0);
767 QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1);
768 QVERIFY(target == 0);
769 QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0);
770 QVERIFY(target != 0);
771 QVERIFY(target->isValid());
772 QCOMPARE(target->object(), (QObject*)w31);
773 delete iface; iface = 0;
775 iface = target->parent();
777 QVERIFY(iface->isValid());
778 QCOMPARE(iface->object(), (QObject*)w3);
779 delete iface; iface = 0;
780 delete target; target = 0;
784 QTestAccessibility::clearEvents();
787 #define QSETCOMPARE(thetypename, elements, otherelements) \
788 QCOMPARE((QSet<thetypename>() << elements), (QSet<thetypename>() << otherelements))
790 static QWidget *createWidgets()
792 QWidget *w = new QWidget();
794 QHBoxLayout *box = new QHBoxLayout(w);
797 box->addWidget(new QComboBox(w));
798 box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
799 box->addWidget(new QHeaderView(Qt::Vertical, w));
800 box->addWidget(new QTreeView(w));
801 box->addWidget(new QTreeWidget(w));
802 box->addWidget(new QListView(w));
803 box->addWidget(new QListWidget(w));
804 box->addWidget(new QTableView(w));
805 box->addWidget(new QTableWidget(w));
806 box->addWidget(new QCalendarWidget(w));
807 box->addWidget(new QDialogButtonBox(w));
808 box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
809 box->addWidget(new QFrame(w));
810 box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
811 box->addWidget(new QProgressBar(w));
812 box->addWidget(new QTabWidget(w));
813 box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
814 box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
815 box->addWidget(new QDial(w));
816 box->addWidget(new QScrollBar(w));
817 box->addWidget(new QSlider(w));
818 box->addWidget(new QDateTimeEdit(w));
819 box->addWidget(new QDoubleSpinBox(w));
820 box->addWidget(new QSpinBox(w));
821 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
822 box->addWidget(new QLCDNumber(w));
823 box->addWidget(new QStackedWidget(w));
824 box->addWidget(new QToolBox(w));
825 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
826 box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
829 * QAbstractItemView, QGraphicsView, QScrollArea,
830 * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
831 * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
836 void tst_QAccessibility::accessibleName()
838 QWidget *toplevel = createWidgets();
840 #if defined(Q_OS_UNIX)
841 QCoreApplication::processEvents();
844 QLayout *lout = toplevel->layout();
845 for (int i = 0; i < lout->count(); i++) {
846 QLayoutItem *item = lout->itemAt(i);
847 QWidget *child = item->widget();
849 QString name = tr("Widget Name %1").arg(i);
850 child->setAccessibleName(name);
851 QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
852 QCOMPARE(acc->text(QAccessible::Name), name);
854 QString desc = tr("Widget Description %1").arg(i);
855 child->setAccessibleDescription(desc);
856 QCOMPARE(acc->text(QAccessible::Description), desc);
861 QTestAccessibility::clearEvents();
864 void tst_QAccessibility::textAttributes()
870 QString text("<html><head></head><body>"
871 "Hello, <b>this</b> is an <i><b>example</b> text</i>."
872 "<span style=\"font-family: monospace\">Multiple fonts are used.</span>"
873 "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used."
874 "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."
877 textEdit.setText(text);
878 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit);
880 QAccessibleTextInterface *textInterface=interface->textInterface();
882 QVERIFY(textInterface);
883 QCOMPARE(textInterface->characterCount(), 112);
885 attributes = textInterface->attributes(10, &startOffset, &endOffset);
886 QCOMPARE(startOffset, 7);
887 QCOMPARE(endOffset, 11);
888 attributes.prepend(';');
889 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
891 attributes = textInterface->attributes(18, &startOffset, &endOffset);
892 QCOMPARE(startOffset, 18);
893 QCOMPARE(endOffset, 25);
894 attributes.prepend(';');
895 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
896 QVERIFY(attributes.contains(QLatin1String(";font-style:italic;")));
898 attributes = textInterface->attributes(34, &startOffset, &endOffset);
899 QCOMPARE(startOffset, 31);
900 QCOMPARE(endOffset, 55);
901 attributes.prepend(';');
902 QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";")));
904 attributes = textInterface->attributes(65, &startOffset, &endOffset);
905 QCOMPARE(startOffset, 64);
906 QCOMPARE(endOffset, 74);
907 attributes.prepend(';');
908 QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;")));
910 attributes = textInterface->attributes(110, &startOffset, &endOffset);
911 QCOMPARE(startOffset, 109);
912 QCOMPARE(endOffset, 111);
913 attributes.prepend(';');
914 QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);")));
915 QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);")));
918 void tst_QAccessibility::hideShowTest()
920 QWidget * const window = new QWidget();
921 QWidget * const child = new QWidget(window);
923 QVERIFY(state(window) & QAccessible::Invisible);
924 QVERIFY(state(child) & QAccessible::Invisible);
926 QTestAccessibility::clearEvents();
928 // show() and veryfy that both window and child are not invisible and get ObjectShow events.
930 QVERIFY(state(window) ^ QAccessible::Invisible);
931 QVERIFY(state(child) ^ QAccessible::Invisible);
932 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
933 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
934 QTestAccessibility::clearEvents();
936 // hide() and veryfy that both window and child are invisible and get ObjectHide events.
938 QVERIFY(state(window) & QAccessible::Invisible);
939 QVERIFY(state(child) & QAccessible::Invisible);
940 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
941 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
942 QTestAccessibility::clearEvents();
945 QTestAccessibility::clearEvents();
949 void tst_QAccessibility::actionTest()
952 QCOMPARE(QAccessibleActionInterface::pressAction(), QString(QStringLiteral("Press")));
954 QWidget *widget = new QWidget;
955 widget->setFocusPolicy(Qt::NoFocus);
958 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(widget);
960 QVERIFY(interface->isValid());
961 QAccessibleActionInterface *actions = interface->actionInterface();
964 // no actions by default, except when focusable
965 QCOMPARE(actions->actionNames(), QStringList());
966 widget->setFocusPolicy(Qt::StrongFocus);
967 QCOMPARE(actions->actionNames(), QStringList(QAccessibleActionInterface::setFocusAction()));
972 QTestAccessibility::clearEvents();
975 QPushButton *button = new QPushButton;
977 button->clearFocus();
978 QCOMPARE(button->hasFocus(), false);
979 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
980 QAccessibleActionInterface *actions = interface->actionInterface();
983 // Make sure the "primary action" press comes first!
984 QCOMPARE(actions->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
986 actions->doAction(QAccessibleActionInterface::setFocusAction());
988 QCOMPARE(button->hasFocus(), true);
990 connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
991 QCOMPARE(click_count, 0);
992 actions->doAction(QAccessibleActionInterface::pressAction());
994 QCOMPARE(click_count, 1);
999 QTestAccessibility::clearEvents();
1002 void tst_QAccessibility::applicationTest()
1004 QLatin1String name = QLatin1String("My Name");
1005 qApp->setApplicationName(name);
1006 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp);
1007 QCOMPARE(interface->text(QAccessible::Name), name);
1008 QCOMPARE(interface->role(), QAccessible::Application);
1012 void tst_QAccessibility::mainWindowTest()
1014 QMainWindow *mw = new QMainWindow;
1015 mw->resize(300, 200);
1016 mw->show(); // triggers layout
1018 QLatin1String name = QLatin1String("I am the main window");
1019 mw->setWindowTitle(name);
1020 QTest::qWaitForWindowShown(mw);
1021 QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
1023 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
1024 QCOMPARE(interface->text(QAccessible::Name), name);
1025 QCOMPARE(interface->role(), QAccessible::Window);
1028 QTestAccessibility::clearEvents();
1031 class CounterButton : public QPushButton {
1034 CounterButton(const QString& name, QWidget* parent)
1035 : QPushButton(name, parent), clickCount(0)
1037 connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount()));
1041 void incClickCount() {
1046 void tst_QAccessibility::buttonTest()
1049 window.setLayout(new QVBoxLayout);
1051 // Standard push button
1052 CounterButton pushButton("Ok", &window);
1055 QPushButton toggleButton("Toggle", &window);
1056 toggleButton.setCheckable(true);
1058 // standard checkbox
1059 QCheckBox checkBox("Check me!", &window);
1061 // tristate checkbox
1062 QCheckBox tristate("Tristate!", &window);
1063 tristate.setTristate(TRUE);
1066 QRadioButton radio("Radio me!", &window);
1068 // standard toolbutton
1069 QToolButton toolbutton(&window);
1070 toolbutton.setText("Tool");
1071 toolbutton.setMinimumSize(20,20);
1073 // standard toolbutton
1074 QToolButton toggletool(&window);
1075 toggletool.setCheckable(true);
1076 toggletool.setText("Toggle");
1077 toggletool.setMinimumSize(20,20);
1080 QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton);
1081 QAccessibleActionInterface* actionInterface = interface->actionInterface();
1082 QVERIFY(actionInterface != 0);
1083 QCOMPARE(interface->role(), QAccessible::PushButton);
1085 // buttons only have a click action
1086 QCOMPARE(actionInterface->actionNames().size(), 2);
1087 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
1088 QCOMPARE(pushButton.clickCount, 0);
1089 actionInterface->doAction(QAccessibleActionInterface::pressAction());
1091 QCOMPARE(pushButton.clickCount, 1);
1094 // test toggle button
1095 interface = QAccessible::queryAccessibleInterface(&toggleButton);
1096 actionInterface = interface->actionInterface();
1097 QCOMPARE(interface->role(), QAccessible::CheckBox);
1098 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1099 QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
1100 QVERIFY(!toggleButton.isChecked());
1101 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1102 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1104 QVERIFY(toggleButton.isChecked());
1105 QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
1106 QVERIFY(interface->state() & QAccessible::Checked);
1110 // test menu push button
1111 QAction *foo = new QAction("Foo", 0);
1112 foo->setShortcut(QKeySequence("Ctrl+F"));
1113 QMenu *menu = new QMenu();
1114 menu->addAction(foo);
1115 QPushButton menuButton;
1116 menuButton.setMenu(menu);
1118 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
1119 QCOMPARE(interface->role(), QAccessible::ButtonMenu);
1120 QVERIFY(interface->state() & QAccessible::HasPopup);
1121 QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction());
1122 // showing the menu enters a new event loop...
1123 // interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1124 // QTest::qWait(500);
1130 interface = QAccessible::queryAccessibleInterface(&checkBox);
1131 actionInterface = interface->actionInterface();
1132 QCOMPARE(interface->role(), QAccessible::CheckBox);
1133 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1134 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1135 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1137 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
1138 QVERIFY(interface->state() & QAccessible::Checked);
1139 QVERIFY(checkBox.isChecked());
1143 interface = QAccessible::queryAccessibleInterface(&radio);
1144 actionInterface = interface->actionInterface();
1145 QCOMPARE(interface->role(), QAccessible::RadioButton);
1146 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1147 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1148 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1150 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1151 QVERIFY(interface->state() & QAccessible::Checked);
1152 QVERIFY(checkBox.isChecked());
1155 // // test standard toolbutton
1156 // QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
1157 // QCOMPARE(test->role(), QAccessible::PushButton);
1158 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1159 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1160 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1163 // // toggle tool button
1164 // QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test));
1165 // QCOMPARE(test->role(), QAccessible::CheckBox);
1166 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1167 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check"));
1168 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1169 // QVERIFY(test->doAction(QAccessible::Press, 0));
1170 // QTest::qWait(500);
1171 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck"));
1172 // QCOMPARE(test->state(), (int)QAccessible::Checked);
1175 // // test menu toolbutton
1176 // QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test));
1177 // QCOMPARE(test->role(), QAccessible::ButtonMenu);
1178 // QCOMPARE(test->defaultAction(0), 1);
1179 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open"));
1180 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1181 // QCOMPARE(test->actionCount(0), 1);
1182 // QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
1185 // // test split menu toolbutton
1186 // QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
1187 // QCOMPARE(test->childCount(), 2);
1188 // QCOMPARE(test->role(), QAccessible::ButtonDropDown);
1189 // QCOMPARE(test->role(1), QAccessible::PushButton);
1190 // QCOMPARE(test->role(2), QAccessible::ButtonMenu);
1191 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1192 // QCOMPARE(test->defaultAction(1), QAccessible::Press);
1193 // QCOMPARE(test->defaultAction(2), QAccessible::Press);
1194 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1195 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1196 // QCOMPARE(test->actionCount(0), 1);
1197 // QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open"));
1198 // QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press"));
1199 // QCOMPARE(test->state(1), (int)QAccessible::Normal);
1200 // QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
1201 // QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
1204 QTestAccessibility::clearEvents();
1207 void tst_QAccessibility::scrollBarTest()
1209 QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
1210 QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
1211 QVERIFY(scrollBarInterface);
1212 QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
1213 scrollBar->resize(200, 50);
1215 QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible);
1216 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
1217 QTestAccessibility::clearEvents();
1220 QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
1221 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
1222 QTestAccessibility::clearEvents();
1224 // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
1226 scrollBar->setMinimum(11);
1227 scrollBar->setMaximum(111);
1229 QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface();
1230 QVERIFY(valueIface != 0);
1231 QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum());
1232 QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum());
1233 scrollBar->setValue(50);
1234 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1235 scrollBar->setValue(0);
1236 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1237 scrollBar->setValue(100);
1238 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1239 valueIface->setCurrentValue(77);
1240 QCOMPARE(77, scrollBar->value());
1242 const QRect scrollBarRect = scrollBarInterface->rect();
1243 QVERIFY(scrollBarRect.isValid());
1245 delete scrollBarInterface;
1248 QTestAccessibility::clearEvents();
1251 void tst_QAccessibility::tabTest()
1253 QTabBar *tabBar = new QTabBar();
1256 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar);
1258 QCOMPARE(interface->childCount(), 2);
1260 // Test that the Invisible bit for the navigation buttons gets set
1261 // and cleared correctly.
1262 QAccessibleInterface *leftButton = interface->child(0);
1263 QCOMPARE(leftButton->role(), QAccessible::PushButton);
1264 QVERIFY(leftButton->state() & QAccessible::Invisible);
1268 for (int i = 0; i < lots; ++i)
1269 tabBar->addTab("Foo");
1271 QAccessibleInterface *child1 = interface->child(0);
1272 QAccessibleInterface *child2 = interface->child(1);
1274 QCOMPARE(child1->role(), QAccessible::PageTab);
1276 QCOMPARE(child2->role(), QAccessible::PageTab);
1278 QVERIFY((child1->state() & QAccessible::Invisible) == false);
1281 QCoreApplication::processEvents();
1284 QVERIFY(child1->state() & QAccessible::Invisible);
1287 tabBar->setCurrentIndex(0);
1289 // Test that sending a focus action to a tab does not select it.
1290 // child2->doAction(QAccessible::Focus, 2, QVariantList());
1291 QCOMPARE(tabBar->currentIndex(), 0);
1293 // Test that sending a press action to a tab selects it.
1294 QVERIFY(child2->actionInterface());
1295 QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1296 QCOMPARE(tabBar->currentIndex(), 0);
1297 child2->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
1298 QCOMPARE(tabBar->currentIndex(), 1);
1304 QTestAccessibility::clearEvents();
1307 void tst_QAccessibility::tabWidgetTest()
1309 QTabWidget *tabWidget = new QTabWidget();
1312 // the interface for the tab is just a container for tabbar and stacked widget
1313 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget);
1315 QCOMPARE(interface->childCount(), 2);
1316 QCOMPARE(interface->role(), QAccessible::Client);
1318 // Create pages, check navigation
1319 QLabel *label1 = new QLabel("Page 1", tabWidget);
1320 tabWidget->addTab(label1, "Tab 1");
1321 QLabel *label2 = new QLabel("Page 2", tabWidget);
1322 tabWidget->addTab(label2, "Tab 2");
1324 QCOMPARE(interface->childCount(), 2);
1326 QAccessibleInterface* tabBarInterface = 0;
1327 // there is no special logic to sort the children, so the contents will be 1, the tab bar 2
1328 tabBarInterface = interface->child(1);
1329 QVERIFY(tabBarInterface);
1330 QCOMPARE(tabBarInterface->childCount(), 4);
1331 QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList);
1333 QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0);
1334 QVERIFY(tabButton1Interface);
1335 QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab);
1336 QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1"));
1338 QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1);
1339 QVERIFY(tabButton1Interface);
1340 QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab);
1341 QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2"));
1343 QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2);
1344 QVERIFY(tabButtonLeft);
1345 QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton);
1346 QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left"));
1348 QAccessibleInterface* tabButtonRight = tabBarInterface->child(3);
1349 QVERIFY(tabButtonRight);
1350 QCOMPARE(tabButtonRight->role(), QAccessible::PushButton);
1351 QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right"));
1352 delete tabButton1Interface;
1353 delete tabButton2Interface;
1354 delete tabButtonLeft;
1355 delete tabButtonRight;
1357 QAccessibleInterface* stackWidgetInterface = interface->child(0);
1358 QVERIFY(stackWidgetInterface);
1359 QCOMPARE(stackWidgetInterface->childCount(), 2);
1360 QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane);
1362 QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0);
1363 QVERIFY(stackChild1Interface);
1365 QCOMPARE(stackChild1Interface->childCount(), 0);
1367 QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText);
1368 QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1"));
1369 QCOMPARE(label1, stackChild1Interface->object());
1371 // Navigation in stack widgets should be consistent
1372 QAccessibleInterface* parent = stackChild1Interface->parent();
1375 QCOMPARE(parent->childCount(), 2);
1377 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1380 QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1);
1381 QVERIFY(stackChild2Interface);
1382 QCOMPARE(stackChild2Interface->childCount(), 0);
1383 QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText);
1384 QCOMPARE(label2, stackChild2Interface->object());
1385 QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name));
1387 parent = stackChild2Interface->parent();
1390 QCOMPARE(parent->childCount(), 2);
1392 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1395 delete tabBarInterface;
1396 delete stackChild1Interface;
1397 delete stackChild2Interface;
1398 delete stackWidgetInterface;
1401 QTestAccessibility::clearEvents();
1404 void tst_QAccessibility::menuTest()
1408 mw.resize(300, 200);
1409 QMenu *file = mw.menuBar()->addMenu("&File");
1410 QMenu *fileNew = file->addMenu("&New...");
1411 fileNew->menuAction()->setShortcut(tr("Ctrl+N"));
1412 fileNew->addAction("Text file");
1413 fileNew->addAction("Image file");
1414 file->addAction("&Open")->setShortcut(tr("Ctrl+O"));
1415 file->addAction("&Save")->setShortcut(tr("Ctrl+S"));
1416 file->addSeparator();
1417 file->addAction("E&xit")->setShortcut(tr("Alt+F4"));
1419 QMenu *edit = mw.menuBar()->addMenu("&Edit");
1420 edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z"));
1421 edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y"));
1422 edit->addSeparator();
1423 edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X"));
1424 edit->addAction("&Copy")->setShortcut(tr("Ctrl+C"));
1425 edit->addAction("&Paste")->setShortcut(tr("Ctrl+V"));
1426 edit->addAction("&Delete")->setShortcut(tr("Del"));
1427 edit->addSeparator();
1428 edit->addAction("Pr&operties");
1430 mw.menuBar()->addSeparator();
1432 QMenu *help = mw.menuBar()->addMenu("&Help");
1433 help->addAction("&Contents");
1434 help->addAction("&About");
1436 mw.menuBar()->addAction("Action!");
1438 mw.show(); // triggers layout
1441 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
1442 QCOMPARE(verifyHierarchy(interface), 0);
1445 QCOMPARE(interface->childCount(), 5);
1446 QCOMPARE(interface->role(), QAccessible::MenuBar);
1448 QAccessibleInterface *iFile = interface->child(0);
1449 QAccessibleInterface *iEdit = interface->child(1);
1450 QAccessibleInterface *iSeparator = interface->child(2);
1451 QAccessibleInterface *iHelp = interface->child(3);
1452 QAccessibleInterface *iAction = interface->child(4);
1454 QCOMPARE(iFile->role(), QAccessible::MenuItem);
1455 QCOMPARE(iEdit->role(), QAccessible::MenuItem);
1456 QCOMPARE(iSeparator->role(), QAccessible::Separator);
1457 QCOMPARE(iHelp->role(), QAccessible::MenuItem);
1458 QCOMPARE(iAction->role(), QAccessible::MenuItem);
1461 if (!IsValidCEPlatform())
1462 QSKIP("Tests do not work on Mobile platforms due to native menus");
1464 QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft());
1465 QCOMPARE(interface->rect().size(), mw.menuBar()->size());
1467 QVERIFY(interface->rect().contains(iFile->rect()));
1468 QVERIFY(interface->rect().contains(iEdit->rect()));
1469 // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible
1470 QVERIFY(interface->rect().contains(iHelp->rect()));
1471 QVERIFY(interface->rect().contains(iAction->rect()));
1474 QCOMPARE(iFile->text(QAccessible::Name), QString("File"));
1475 QCOMPARE(iEdit->text(QAccessible::Name), QString("Edit"));
1476 QCOMPARE(iSeparator->text(QAccessible::Name), QString());
1477 QCOMPARE(iHelp->text(QAccessible::Name), QString("Help"));
1478 QCOMPARE(iAction->text(QAccessible::Name), QString("Action!"));
1480 // TODO: Currently not working, task to fix is #100019.
1482 QCOMPARE(iFile->text(QAccessible::Accelerator), tr("Alt+F"));
1483 QCOMPARE(iEdit->text(QAccessible::Accelerator), tr("Alt+E"));
1484 QCOMPARE(iSeparator->text(QAccessible::Accelerator), QString());
1485 QCOMPARE(iHelp->text(QAccessible::Accelerator), tr("Alt+H"));
1486 QCOMPARE(iAction->text(QAccessible::Accelerator), QString());
1489 QVERIFY(iFile->actionInterface());
1491 QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1492 QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList());
1493 QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1494 QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1496 bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu);
1497 int menuFadeDelay = 300;
1498 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1500 QTest::qWait(menuFadeDelay);
1501 QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible());
1502 iEdit->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1504 QTest::qWait(menuFadeDelay);
1505 QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible());
1506 iHelp->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1508 QTest::qWait(menuFadeDelay);
1509 QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible());
1510 iAction->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1512 QTest::qWait(menuFadeDelay);
1513 QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible());
1515 QVERIFY(interface->actionInterface());
1516 QCOMPARE(interface->actionInterface()->actionNames(), QStringList());
1518 interface = QAccessible::queryAccessibleInterface(file);
1519 QCOMPARE(interface->childCount(), 5);
1520 QCOMPARE(interface->role(), QAccessible::PopupMenu);
1522 QAccessibleInterface *iFileNew = interface->child(0);
1523 QAccessibleInterface *iFileOpen = interface->child(1);
1524 QAccessibleInterface *iFileSave = interface->child(2);
1525 QAccessibleInterface *iFileSeparator = interface->child(3);
1526 QAccessibleInterface *iFileExit = interface->child(4);
1528 QCOMPARE(iFileNew->role(), QAccessible::MenuItem);
1529 QCOMPARE(iFileOpen->role(), QAccessible::MenuItem);
1530 QCOMPARE(iFileSave->role(), QAccessible::MenuItem);
1531 QCOMPARE(iFileSeparator->role(), QAccessible::Separator);
1532 QCOMPARE(iFileExit->role(), QAccessible::MenuItem);
1533 QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1534 QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1535 QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1536 QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList());
1537 QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1539 QAccessibleInterface *iface = 0;
1540 QAccessibleInterface *iface2 = 0;
1542 // traverse siblings with navigate(Sibling, ...)
1544 iface = interface->child(0);
1546 QCOMPARE(iface->role(), QAccessible::MenuItem);
1548 QAccessible::Role fileRoles[5] = {
1549 QAccessible::MenuItem,
1550 QAccessible::MenuItem,
1551 QAccessible::MenuItem,
1552 QAccessible::Separator,
1553 QAccessible::MenuItem
1555 for (int child = 0; child < 5; ++child) {
1556 entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2);
1559 QCOMPARE(iface2->role(), fileRoles[child]);
1564 // traverse menu items with navigate(Down, ...)
1565 iface = interface->child(0);
1567 QCOMPARE(iface->role(), QAccessible::MenuItem);
1569 for (int child = 0; child < 4; ++child) {
1570 entry = iface->navigate(QAccessible::Down, 1, &iface2);
1575 QCOMPARE(iface->role(), fileRoles[child + 1]);
1579 // traverse menu items with navigate(Up, ...)
1580 iface = interface->child(interface->childCount() - 1);
1582 QCOMPARE(iface->role(), QAccessible::MenuItem);
1584 for (int child = 3; child >= 0; --child) {
1585 entry = iface->navigate(QAccessible::Up, 1, &iface2);
1590 QCOMPARE(iface->role(), fileRoles[child]);
1595 iface = interface->child(0);
1597 QCOMPARE(iface->role(), QAccessible::MenuItem);
1600 iface2 = iface->child(0);
1605 QCOMPARE(iface->role(), QAccessible::PopupMenu);
1607 // "Text file" menu item
1608 iface2 = iface->child(0);
1612 QCOMPARE(iface->role(), QAccessible::MenuItem);
1616 // move mouse pointer away, since that might influence the
1618 QTest::mouseMove(&mw, QPoint(-1, -1));
1621 QTest::qWait(menuFadeDelay);
1623 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1624 iFileNew->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1626 QVERIFY(file->isVisible());
1627 QVERIFY(fileNew->isVisible());
1628 QVERIFY(!edit->isVisible());
1629 QVERIFY(!help->isVisible());
1631 QTestAccessibility::clearEvents();
1638 delete iFileSeparator;
1641 // Do not crash if the menu don't have a parent
1642 QMenu *menu = new QMenu;
1643 menu->addAction(QLatin1String("one"));
1644 menu->addAction(QLatin1String("two"));
1645 menu->addAction(QLatin1String("three"));
1646 iface = QAccessible::queryAccessibleInterface(menu);
1647 iface2 = iface->parent();
1649 QCOMPARE(iface2->role(), QAccessible::Application);
1657 QTestAccessibility::clearEvents();
1660 void tst_QAccessibility::spinBoxTest()
1662 QSpinBox * const spinBox = new QSpinBox();
1663 spinBox->setValue(3);
1666 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox);
1668 QCOMPARE(interface->role(), QAccessible::SpinBox);
1670 const QRect widgetRect = spinBox->geometry();
1671 const QRect accessibleRect = interface->rect();
1672 QCOMPARE(accessibleRect, widgetRect);
1673 QCOMPARE(interface->text(QAccessible::Value), QLatin1String("3"));
1675 // one child, the line edit
1676 const int numChildren = interface->childCount();
1677 QCOMPARE(numChildren, 1);
1678 QAccessibleInterface *lineEdit = interface->child(0);
1680 QCOMPARE(lineEdit->role(), QAccessible::EditableText);
1681 QCOMPARE(lineEdit->text(QAccessible::Value), QLatin1String("3"));
1684 QVERIFY(interface->valueInterface());
1685 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3);
1686 interface->valueInterface()->setCurrentValue(23);
1687 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23);
1688 QCOMPARE(spinBox->value(), 23);
1690 spinBox->setFocus();
1691 QTestAccessibility::clearEvents();
1692 QTest::keyPress(spinBox, Qt::Key_Up);
1694 EventList events = QTestAccessibility::events();
1695 QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
1696 QVERIFY(events.contains(expectedEvent));
1698 QTestAccessibility::clearEvents();
1701 void tst_QAccessibility::doubleSpinBoxTest()
1703 QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox;
1704 doubleSpinBox->show();
1706 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
1709 const QRect widgetRect = doubleSpinBox->geometry();
1710 const QRect accessibleRect = interface->rect();
1711 QCOMPARE(accessibleRect, widgetRect);
1713 // Test that we get valid rects for all the spinbox child interfaces.
1714 const int numChildren = interface->childCount();
1715 for (int i = 0; i < numChildren; ++i) {
1716 QAccessibleInterface *childIface = interface->child(i);
1717 const QRect childRect = childIface->rect();
1718 QVERIFY(childRect.isValid());
1722 delete doubleSpinBox;
1723 QTestAccessibility::clearEvents();
1726 void tst_QAccessibility::textEditTest()
1732 QString text = "hello world\nhow are you today?\n";
1736 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
1737 QCOMPARE(iface->text(QAccessible::Value), text);
1738 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1739 QCOMPARE(startOffset, 6);
1740 QCOMPARE(endOffset, 11);
1741 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1742 QCOMPARE(startOffset, 12);
1743 QCOMPARE(endOffset, 30);
1744 QCOMPARE(iface->textInterface()->characterCount(), 31);
1745 QFontMetrics fm(edit.font());
1746 QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
1747 QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
1748 QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
1750 QTestAccessibility::clearEvents();
1753 void tst_QAccessibility::textBrowserTest()
1756 QTextBrowser textBrowser;
1757 QString text = QLatin1String("Hello world\nhow are you today?\n");
1758 textBrowser.setText(text);
1761 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
1763 QCOMPARE(iface->role(), QAccessible::StaticText);
1764 QCOMPARE(iface->text(QAccessible::Value), text);
1767 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1768 QCOMPARE(startOffset, 6);
1769 QCOMPARE(endOffset, 11);
1770 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1771 QCOMPARE(startOffset, 12);
1772 QCOMPARE(endOffset, 30);
1773 QCOMPARE(iface->textInterface()->characterCount(), 31);
1775 QTestAccessibility::clearEvents();
1778 void tst_QAccessibility::mdiAreaTest()
1782 mdiArea.resize(400,300);
1784 const int subWindowCount = 3;
1785 for (int i = 0; i < subWindowCount; ++i)
1786 mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show();
1788 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1789 QCOMPARE(subWindows.count(), subWindowCount);
1791 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea);
1793 QCOMPARE(interface->childCount(), subWindowCount);
1795 // Right, right, right, ...
1796 for (int i = 0; i < subWindowCount; ++i) {
1797 QAccessibleInterface *destination = 0;
1798 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
1799 if (i == subWindowCount - 1) {
1800 QVERIFY(!destination);
1801 QCOMPARE(index, -1);
1803 QVERIFY(destination);
1805 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
1810 // Left, left, left, ...
1811 for (int i = subWindowCount; i > 0; --i) {
1812 QAccessibleInterface *destination = 0;
1813 int index = interface->navigate(QAccessible::Left, i, &destination);
1815 QVERIFY(!destination);
1816 QCOMPARE(index, -1);
1818 QVERIFY(destination);
1820 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
1824 // ### Add test for Up and Down.
1827 QTestAccessibility::clearEvents();
1830 void tst_QAccessibility::mdiSubWindowTest()
1835 qApp->setActiveWindow(&mdiArea);
1836 #if defined(Q_OS_UNIX)
1837 QCoreApplication::processEvents();
1841 bool isSubWindowsPlacedNextToEachOther = false;
1842 const int subWindowCount = 5;
1843 for (int i = 0; i < subWindowCount; ++i) {
1844 QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
1846 // Parts of this test requires that the sub windows are placed next
1847 // to each other. In order to achieve that QMdiArea must have
1848 // a width which is larger than subWindow->width() * subWindowCount.
1850 int minimumWidth = window->width() * subWindowCount + 20;
1851 mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0)));
1852 #if defined(Q_OS_UNIX)
1853 QCoreApplication::processEvents();
1856 if (mdiArea.width() >= minimumWidth)
1857 isSubWindowsPlacedNextToEachOther = true;
1861 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1862 QCOMPARE(subWindows.count(), subWindowCount);
1864 QMdiSubWindow *testWindow = subWindows.at(3);
1865 QVERIFY(testWindow);
1866 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow);
1870 QCOMPARE(interface->childCount(), 1);
1873 QCOMPARE(interface->text(QAccessible::Name), QString());
1874 testWindow->setWindowTitle(QLatin1String("ReplaceMe"));
1875 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("ReplaceMe"));
1876 interface->setText(QAccessible::Name, QLatin1String("TitleSetOnWindow"));
1877 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("TitleSetOnWindow"));
1879 mdiArea.setActiveSubWindow(testWindow);
1882 QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused
1883 | QAccessible::Movable | QAccessible::Sizeable;
1884 QCOMPARE(interface->state(), state);
1885 const QRect originalGeometry = testWindow->geometry();
1886 testWindow->showMaximized();
1887 state &= (uint)~QAccessible::Sizeable;
1888 state &= (uint)~QAccessible::Movable;
1889 QCOMPARE(interface->state(), state);
1890 testWindow->showNormal();
1891 testWindow->move(-10, 0);
1892 QVERIFY(interface->state() & QAccessible::Offscreen);
1893 testWindow->setVisible(false);
1894 QVERIFY(interface->state() & QAccessible::Invisible);
1895 testWindow->setVisible(true);
1896 testWindow->setEnabled(false);
1897 QVERIFY(interface->state() & QAccessible::Unavailable);
1898 testWindow->setEnabled(true);
1899 qApp->setActiveWindow(&mdiArea);
1900 mdiArea.setActiveSubWindow(testWindow);
1901 testWindow->setFocus();
1902 QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
1903 QVERIFY(interface->state() & QAccessible::Focused);
1904 testWindow->setGeometry(originalGeometry);
1906 if (isSubWindowsPlacedNextToEachOther) {
1907 // This part of the test can only be run if the sub windows are
1908 // placed next to each other.
1909 QAccessibleInterface *destination = interface->child(0);
1910 QVERIFY(destination);
1911 QCOMPARE(destination->object(), (QObject*)testWindow->widget());
1913 QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0);
1914 QVERIFY(destination);
1915 QCOMPARE(destination->object(), (QObject*)subWindows.at(2));
1917 QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0);
1918 QVERIFY(destination);
1919 QCOMPARE(destination->object(), (QObject*)subWindows.at(4));
1924 const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0));
1925 QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size()));
1927 QCOMPARE(interface->rect(), QRect());
1928 QCOMPARE(childRect(interface), QRect());
1929 testWindow->showMinimized();
1930 QCOMPARE(childRect(interface), QRect());
1931 testWindow->showNormal();
1932 testWindow->widget()->hide();
1933 QCOMPARE(childRect(interface), QRect());
1934 testWindow->widget()->show();
1935 const QRect widgetGeometry = testWindow->contentsRect();
1936 const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
1937 globalPos.y() + widgetGeometry.y());
1938 QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
1941 QCOMPARE(interface->childAt(-10, 0), static_cast<QAccessibleInterface*>(0));
1942 QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), static_cast<QAccessibleInterface*>(0));
1943 QAccessibleInterface *child = interface->childAt(globalWidgetPos.x(), globalWidgetPos.y());
1944 QCOMPARE(child->role(), QAccessible::PushButton);
1945 QCOMPARE(child->text(QAccessible::Name), QString("QAccessibilityTest"));
1947 testWindow->widget()->hide();
1948 QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), static_cast<QAccessibleInterface*>(0));
1951 QTestAccessibility::clearEvents();
1954 void tst_QAccessibility::lineEditTest()
1956 QLineEdit *le = new QLineEdit;
1957 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
1961 QApplication::processEvents();
1962 QCOMPARE(iface->childCount(), 0);
1963 QVERIFY(iface->state() & QAccessible::Sizeable);
1964 QVERIFY(iface->state() & QAccessible::Movable);
1965 QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1966 QVERIFY(iface->state() & QAccessible::Selectable);
1967 QVERIFY(iface->state() & QAccessible::HasPopup);
1968 QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1970 QString secret(QLatin1String("secret"));
1971 le->setText(secret);
1972 le->setEchoMode(QLineEdit::Normal);
1973 QVERIFY(!(iface->state() & QAccessible::Protected));
1974 QCOMPARE(iface->text(QAccessible::Value), secret);
1975 le->setEchoMode(QLineEdit::NoEcho);
1976 QVERIFY(iface->state() & QAccessible::Protected);
1977 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1978 le->setEchoMode(QLineEdit::Password);
1979 QVERIFY(iface->state() & QAccessible::Protected);
1980 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1981 le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
1982 QVERIFY(iface->state() & QAccessible::Protected);
1983 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1984 le->setEchoMode(QLineEdit::Normal);
1985 QVERIFY(!(iface->state() & QAccessible::Protected));
1986 QCOMPARE(iface->text(QAccessible::Value), secret);
1988 QWidget *toplevel = new QWidget;
1989 le->setParent(toplevel);
1991 QApplication::processEvents();
1992 QVERIFY(!(iface->state() & QAccessible::Sizeable));
1993 QVERIFY(!(iface->state() & QAccessible::Movable));
1994 QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1995 QVERIFY(iface->state() & QAccessible::Selectable);
1996 QVERIFY(iface->state() & QAccessible::HasPopup);
1997 QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1999 QLineEdit *le2 = new QLineEdit(toplevel);
2002 le2->activateWindow();
2004 le->setFocus(Qt::TabFocusReason);
2005 QTestAccessibility::clearEvents();
2006 le2->setFocus(Qt::TabFocusReason);
2007 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
2009 le->setText(QLatin1String("500"));
2010 le->setValidator(new QIntValidator());
2011 iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
2012 QCOMPARE(le->text(), QLatin1String("500"));
2017 QTestAccessibility::clearEvents();
2020 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";
2021 QLineEdit *le3 = new QLineEdit(cite, toplevel);
2022 iface = QAccessible::queryAccessibleInterface(le3);
2023 QAccessibleTextInterface* textIface = iface->textInterface();
2025 le3->setCursorPosition(3);
2026 QCOMPARE(textIface->cursorPosition(), 3);
2027 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
2028 QCOMPARE(textIface->selectionCount(), 0);
2029 QTestAccessibility::clearEvents();
2032 QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
2033 QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
2036 QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString());
2037 QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" "));
2041 QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a"));
2044 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w"));
2045 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y"));
2047 QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2051 QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2052 QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2053 QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2054 QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
2055 QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
2057 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2058 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2059 QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2063 QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2064 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. "));
2066 QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite);
2068 QCOMPARE(end, cite.length());
2069 QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
2070 QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
2074 QTestAccessibility::clearEvents();
2077 void tst_QAccessibility::workspaceTest()
2080 QWorkspace workspace;
2081 workspace.resize(400,300);
2083 const int subWindowCount = 3;
2084 for (int i = 0; i < subWindowCount; ++i) {
2085 QWidget *window = workspace.addWindow(new QWidget);
2087 window->move(window->x() + 1, window->y());
2089 window->resize(70, window->height());
2092 QWidgetList subWindows = workspace.windowList();
2093 QCOMPARE(subWindows.count(), subWindowCount);
2095 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
2097 QCOMPARE(interface->childCount(), subWindowCount);
2099 // Right, right, right, ...
2100 for (int i = 0; i < subWindowCount; ++i) {
2101 QAccessibleInterface *destination = 0;
2102 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
2103 if (i == subWindowCount - 1) {
2104 QVERIFY(!destination);
2105 QCOMPARE(index, -1);
2107 QVERIFY(destination);
2109 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
2114 // Left, left, left, ...
2115 for (int i = subWindowCount; i > 0; --i) {
2116 QAccessibleInterface *destination = 0;
2117 int index = interface->navigate(QAccessible::Left, i, &destination);
2119 QVERIFY(!destination);
2120 QCOMPARE(index, -1);
2122 QVERIFY(destination);
2124 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
2128 // ### Add test for Up and Down.
2131 QTestAccessibility::clearEvents();
2134 void tst_QAccessibility::dialogButtonBoxTest()
2137 QDialogButtonBox box(QDialogButtonBox::Reset |
2138 QDialogButtonBox::Help |
2139 QDialogButtonBox::Ok, Qt::Horizontal);
2142 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2145 #if defined(Q_OS_UNIX)
2146 QCoreApplication::processEvents();
2150 QApplication::processEvents();
2151 QCOMPARE(iface->childCount(), 3);
2152 QCOMPARE(iface->role(), QAccessible::Grouping);
2153 QStringList actualOrder;
2154 QAccessibleInterface *child;
2155 QAccessibleInterface *leftmost;
2156 child = iface->child(0);
2157 QCOMPARE(child->role(), QAccessible::PushButton);
2159 // first find the leftmost button
2160 while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) {
2166 // then traverse from left to right to find the correct order of the buttons
2168 while (right != -1) {
2169 actualOrder << leftmost->text(QAccessible::Name);
2170 right = leftmost->navigate(QAccessible::Right, 1, &child);
2175 QStringList expectedOrder;
2176 QDialogButtonBox::ButtonLayout btnlout =
2177 QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout));
2179 case QDialogButtonBox::WinLayout:
2180 expectedOrder << QDialogButtonBox::tr("Reset")
2181 << QDialogButtonBox::tr("OK")
2182 << QDialogButtonBox::tr("Help");
2184 case QDialogButtonBox::GnomeLayout:
2185 case QDialogButtonBox::KdeLayout:
2186 case QDialogButtonBox::MacLayout:
2187 expectedOrder << QDialogButtonBox::tr("Help")
2188 << QDialogButtonBox::tr("Reset")
2189 << QDialogButtonBox::tr("OK");
2192 QCOMPARE(actualOrder, expectedOrder);
2194 QApplication::processEvents();
2195 QTestAccessibility::clearEvents();
2199 QDialogButtonBox box(QDialogButtonBox::Reset |
2200 QDialogButtonBox::Help |
2201 QDialogButtonBox::Ok, Qt::Horizontal);
2204 // Test up and down navigation
2205 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2207 box.setOrientation(Qt::Vertical);
2209 #if defined(Q_OS_UNIX)
2210 QCoreApplication::processEvents();
2214 QApplication::processEvents();
2215 QAccessibleInterface *child;
2216 QStringList actualOrder;
2217 child = iface->child(0);
2218 // first find the topmost button
2219 QAccessibleInterface *other;
2220 while (child->navigate(QAccessible::Up, 1, &other) != -1) {
2226 // then traverse from top to bottom to find the correct order of the buttons
2227 actualOrder.clear();
2229 while (right != -1) {
2230 actualOrder << other->text(QAccessible::Name);
2231 right = other->navigate(QAccessible::Down, 1, &child);
2236 QStringList expectedOrder;
2237 expectedOrder << QDialogButtonBox::tr("OK")
2238 << QDialogButtonBox::tr("Reset")
2239 << QDialogButtonBox::tr("Help");
2241 QCOMPARE(actualOrder, expectedOrder);
2243 QApplication::processEvents();
2246 QTestAccessibility::clearEvents();
2249 void tst_QAccessibility::dialTest()
2253 dial.setMinimum(23);
2254 dial.setMaximum(121);
2256 QCOMPARE(dial.value(), 42);
2259 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial);
2261 QCOMPARE(interface->childCount(), 0);
2263 QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value()));
2264 QCOMPARE(interface->rect(), dial.geometry());
2266 QAccessibleValueInterface *valueIface = interface->valueInterface();
2267 QVERIFY(valueIface != 0);
2268 QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum());
2269 QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum());
2270 QCOMPARE(valueIface->currentValue().toInt(), 42);
2272 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2274 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2276 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2277 valueIface->setCurrentValue(77);
2278 QCOMPARE(77, dial.value());
2280 QTestAccessibility::clearEvents();
2283 void tst_QAccessibility::rubberBandTest()
2285 QRubberBand rubberBand(QRubberBand::Rectangle);
2286 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand);
2288 QCOMPARE(interface->role(), QAccessible::Border);
2290 QTestAccessibility::clearEvents();
2293 void tst_QAccessibility::abstractScrollAreaTest()
2296 QAbstractScrollArea abstractScrollArea;
2298 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
2300 QVERIFY(!interface->rect().isValid());
2301 QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
2303 abstractScrollArea.resize(400, 400);
2304 abstractScrollArea.show();
2305 #if defined(Q_OS_UNIX)
2306 QCoreApplication::processEvents();
2309 const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)),
2310 abstractScrollArea.size());
2313 QCOMPARE(interface->childCount(), 1);
2314 QWidget *viewport = abstractScrollArea.viewport();
2316 QVERIFY(verifyChild(viewport, interface, 1, globalGeometry));
2318 // Horizontal scrollBar.
2319 abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2320 QCOMPARE(interface->childCount(), 2);
2321 QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar();
2322 QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget();
2323 QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry));
2325 // Horizontal scrollBar widgets.
2326 QLabel *secondLeftLabel = new QLabel(QLatin1String("L2"));
2327 abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft);
2328 QCOMPARE(interface->childCount(), 2);
2330 QLabel *firstLeftLabel = new QLabel(QLatin1String("L1"));
2331 abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft);
2332 QCOMPARE(interface->childCount(), 2);
2334 QLabel *secondRightLabel = new QLabel(QLatin1String("R2"));
2335 abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight);
2336 QCOMPARE(interface->childCount(), 2);
2338 QLabel *firstRightLabel = new QLabel(QLatin1String("R1"));
2339 abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight);
2340 QCOMPARE(interface->childCount(), 2);
2342 // Vertical scrollBar.
2343 abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2344 QCOMPARE(interface->childCount(), 3);
2345 QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar();
2346 QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget();
2347 QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry));
2349 // Vertical scrollBar widgets.
2350 QLabel *secondTopLabel = new QLabel(QLatin1String("T2"));
2351 abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop);
2352 QCOMPARE(interface->childCount(), 3);
2354 QLabel *firstTopLabel = new QLabel(QLatin1String("T1"));
2355 abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop);
2356 QCOMPARE(interface->childCount(), 3);
2358 QLabel *secondBottomLabel = new QLabel(QLatin1String("B2"));
2359 abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom);
2360 QCOMPARE(interface->childCount(), 3);
2362 QLabel *firstBottomLabel = new QLabel(QLatin1String("B1"));
2363 abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom);
2364 QCOMPARE(interface->childCount(), 3);
2367 abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C")));
2368 QCOMPARE(interface->childCount(), 4);
2369 QWidget *cornerWidget = abstractScrollArea.cornerWidget();
2370 QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry));
2373 QAccessibleInterface *target = 0;
2375 // viewport -> Up -> NOTHING
2376 const int viewportIndex = indexOfChild(interface, viewport);
2377 QVERIFY(viewportIndex != -1);
2378 QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1);
2381 // viewport -> Left -> NOTHING
2382 QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1);
2385 // viewport -> Down -> horizontalScrollBarContainer
2386 const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer);
2387 QVERIFY(horizontalScrollBarContainerIndex != -1);
2388 QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0);
2390 QCOMPARE(target->object(), static_cast<QObject *>(horizontalScrollBarContainer));
2394 // horizontalScrollBarContainer -> Left -> NOTHING
2395 QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1);
2398 // horizontalScrollBarContainer -> Down -> NOTHING
2399 QVERIFY(horizontalScrollBarContainerIndex != -1);
2400 QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1);
2403 // horizontalScrollBarContainer -> Right -> cornerWidget
2404 const int cornerWidgetIndex = indexOfChild(interface, cornerWidget);
2405 QVERIFY(cornerWidgetIndex != -1);
2406 QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0);
2408 QCOMPARE(target->object(), static_cast<QObject *>(cornerWidget));
2412 // cornerWidget -> Down -> NOTHING
2413 QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1);
2416 // cornerWidget -> Right -> NOTHING
2417 QVERIFY(cornerWidgetIndex != -1);
2418 QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1);
2421 // cornerWidget -> Up -> verticalScrollBarContainer
2422 const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer);
2423 QVERIFY(verticalScrollBarContainerIndex != -1);
2424 QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0);
2426 QCOMPARE(target->object(), static_cast<QObject *>(verticalScrollBarContainer));
2430 // verticalScrollBarContainer -> Right -> NOTHING
2431 QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1);
2434 // verticalScrollBarContainer -> Up -> NOTHING
2435 QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1);
2438 // verticalScrollBarContainer -> Left -> viewport
2439 QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0);
2441 QCOMPARE(target->object(), static_cast<QObject *>(viewport));
2445 QCOMPARE(verifyHierarchy(interface), 0);
2450 QTestAccessibility::clearEvents();
2453 void tst_QAccessibility::scrollAreaTest()
2456 QScrollArea scrollArea;
2458 #if defined(Q_OS_UNIX)
2459 QCoreApplication::processEvents();
2462 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea);
2464 QCOMPARE(interface->childCount(), 1); // The viewport.
2467 QTestAccessibility::clearEvents();
2470 void tst_QAccessibility::listTest()
2472 QListWidget *listView = new QListWidget;
2473 listView->addItem("Oslo");
2474 listView->addItem("Berlin");
2475 listView->addItem("Brisbane");
2476 listView->resize(400,400);
2478 QTest::qWait(1); // Need this for indexOfchild to work.
2479 QCoreApplication::processEvents();
2482 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView);
2483 QCOMPARE(verifyHierarchy(iface), 0);
2485 QCOMPARE((int)iface->role(), (int)QAccessible::List);
2486 QCOMPARE(iface->childCount(), 3);
2488 QAccessibleInterface *child1 = 0;
2489 child1 = iface->child(0);
2491 QCOMPARE(iface->indexOfChild(child1), 1);
2492 QCOMPARE(child1->text(QAccessible::Name), QString("Oslo"));
2493 QCOMPARE(child1->role(), QAccessible::ListItem);
2496 QAccessibleInterface *child2 = 0;
2497 child2 = iface->child(1);
2499 QCOMPARE(iface->indexOfChild(child2), 2);
2500 QCOMPARE(child2->text(QAccessible::Name), QString("Berlin"));
2503 QAccessibleInterface *child3 = 0;
2504 child3 = iface->child(2);
2506 QCOMPARE(iface->indexOfChild(child3), 3);
2507 QCOMPARE(child3->text(QAccessible::Name), QString("Brisbane"));
2509 QTestAccessibility::clearEvents();
2512 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
2513 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
2514 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
2515 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
2516 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
2517 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
2519 listView->addItem("Munich");
2520 QCOMPARE(iface->childCount(), 4);
2523 QAccessibleTableInterface *table2 = iface->tableInterface();
2525 QCOMPARE(table2->columnCount(), 1);
2526 QCOMPARE(table2->rowCount(), 4);
2527 QAccessibleInterface *cell1;
2528 QVERIFY(cell1 = table2->cellAt(0,0));
2529 QCOMPARE(cell1->text(QAccessible::Name), QString("Oslo"));
2530 QAccessibleInterface *cell4;
2531 QVERIFY(cell4 = table2->cellAt(3,0));
2532 QCOMPARE(cell4->text(QAccessible::Name), QString("Munich"));
2533 QCOMPARE(cell4->role(), QAccessible::ListItem);
2535 QAccessibleTableCellInterface *cellInterface = cell4->tableCellInterface();
2536 QVERIFY(cellInterface);
2537 QCOMPARE(cellInterface->rowIndex(), 3);
2538 QCOMPARE(cellInterface->columnIndex(), 0);
2539 QVERIFY(!(cell4->state() & QAccessible::Expandable));
2545 QTestAccessibility::clearEvents();
2548 void tst_QAccessibility::treeTest()
2550 QTreeWidget *treeView = new QTreeWidget;
2551 treeView->setColumnCount(2);
2552 QTreeWidgetItem *header = new QTreeWidgetItem;
2553 header->setText(0, "Artist");
2554 header->setText(1, "Work");
2555 treeView->setHeaderItem(header);
2557 QTreeWidgetItem *root1 = new QTreeWidgetItem;
2558 root1->setText(0, "Spain");
2559 treeView->addTopLevelItem(root1);
2561 QTreeWidgetItem *item1 = new QTreeWidgetItem;
2562 item1->setText(0, "Picasso");
2563 item1->setText(1, "Guernica");
2564 root1->addChild(item1);
2566 QTreeWidgetItem *item2 = new QTreeWidgetItem;
2567 item2->setText(0, "Tapies");
2568 item2->setText(1, "Ambrosia");
2569 root1->addChild(item2);
2571 QTreeWidgetItem *root2 = new QTreeWidgetItem;
2572 root2->setText(0, "Austria");
2573 treeView->addTopLevelItem(root2);
2575 QTreeWidgetItem *item3 = new QTreeWidgetItem;
2576 item3->setText(0, "Klimt");
2577 item3->setText(1, "The Kiss");
2578 root2->addChild(item3);
2580 treeView->resize(400,400);
2583 QCoreApplication::processEvents();
2586 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
2587 QCOMPARE(verifyHierarchy(iface), 0);
2589 QCOMPARE((int)iface->role(), (int)QAccessible::Tree);
2590 // header and 2 rows (the others are not expanded, thus not visible)
2591 QCOMPARE(iface->childCount(), 6);
2593 QAccessibleInterface *header1 = 0;
2594 header1 = iface->child(0);
2596 QCOMPARE(iface->indexOfChild(header1), 1);
2597 QCOMPARE(header1->text(QAccessible::Name), QString("Artist"));
2598 QCOMPARE(header1->role(), QAccessible::ColumnHeader);
2601 QAccessibleInterface *child1 = 0;
2602 child1 = iface->child(2);
2604 QCOMPARE(iface->indexOfChild(child1), 3);
2605 QCOMPARE(child1->text(QAccessible::Name), QString("Spain"));
2606 QCOMPARE(child1->role(), QAccessible::TreeItem);
2607 QVERIFY(!(child1->state() & QAccessible::Expanded));
2610 QAccessibleInterface *child2 = 0;
2611 child2 = iface->child(4);
2613 QCOMPARE(iface->indexOfChild(child2), 5);
2614 QCOMPARE(child2->text(QAccessible::Name), QString("Austria"));
2617 QTestAccessibility::clearEvents();
2620 QAccessibleTableInterface *table2 = iface->tableInterface();
2622 QCOMPARE(table2->columnCount(), 2);
2623 QCOMPARE(table2->rowCount(), 2);
2624 QAccessibleInterface *cell1;
2625 QVERIFY(cell1 = table2->cellAt(0,0));
2626 QCOMPARE(cell1->text(QAccessible::Name), QString("Spain"));
2627 QAccessibleInterface *cell2;
2628 QVERIFY(cell2 = table2->cellAt(1,0));
2629 QCOMPARE(cell2->text(QAccessible::Name), QString("Austria"));
2630 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2631 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1);
2632 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2633 QVERIFY(cell2->state() & QAccessible::Expandable);
2634 QCOMPARE(iface->indexOfChild(cell2), 5);
2635 QVERIFY(!(cell2->state() & QAccessible::Expanded));
2636 QCOMPARE(table2->columnDescription(1), QString("Work"));
2640 treeView->expandAll();
2642 // Need this for indexOfchild to work.
2643 QCoreApplication::processEvents();
2646 QCOMPARE(table2->columnCount(), 2);
2647 QCOMPARE(table2->rowCount(), 5);
2648 cell1 = table2->cellAt(1,0);
2649 QCOMPARE(cell1->text(QAccessible::Name), QString("Picasso"));
2650 QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
2652 cell2 = table2->cellAt(4,0);
2653 QCOMPARE(cell2->text(QAccessible::Name), QString("Klimt"));
2654 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2655 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4);
2656 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2657 QVERIFY(!(cell2->state() & QAccessible::Expandable));
2658 QCOMPARE(iface->indexOfChild(cell2), 11);
2660 QCOMPARE(table2->columnDescription(0), QString("Artist"));
2661 QCOMPARE(table2->columnDescription(1), QString("Work"));
2664 QTestAccessibility::clearEvents();
2667 void tst_QAccessibility::tableTest()
2669 QTableWidget *tableView = new QTableWidget(3, 3);
2670 tableView->setColumnCount(3);
2671 QStringList hHeader;
2672 hHeader << "h1" << "h2" << "h3";
2673 tableView->setHorizontalHeaderLabels(hHeader);
2675 QStringList vHeader;
2676 vHeader << "v1" << "v2" << "v3";
2677 tableView->setVerticalHeaderLabels(vHeader);
2679 for (int i = 0; i<9; ++i) {
2680 QTableWidgetItem *item = new QTableWidgetItem;
2681 item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
2682 tableView->setItem(i/3, i%3, item);
2685 tableView->resize(600,600);
2687 QTest::qWait(1); // Need this for indexOfchild to work.
2688 QCoreApplication::processEvents();
2691 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
2692 QCOMPARE(verifyHierarchy(iface), 0);
2694 QCOMPARE((int)iface->role(), (int)QAccessible::Table);
2695 // header and 2 rows (the others are not expanded, thus not visible)
2696 QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
2698 QAccessibleInterface *cornerButton = iface->child(0);
2699 QVERIFY(cornerButton);
2700 QCOMPARE(iface->indexOfChild(cornerButton), 1);
2701 QCOMPARE(cornerButton->role(), QAccessible::Pane);
2702 delete cornerButton;
2704 QAccessibleInterface *child1 = iface->child(2);
2706 QCOMPARE(iface->indexOfChild(child1), 3);
2707 QCOMPARE(child1->text(QAccessible::Name), QString("h2"));
2708 QCOMPARE(child1->role(), QAccessible::ColumnHeader);
2709 QVERIFY(!(child1->state() & QAccessible::Expanded));
2712 QAccessibleInterface *child2 = iface->child(10);
2714 QCOMPARE(iface->indexOfChild(child2), 11);
2715 QCOMPARE(child2->text(QAccessible::Name), QString("1.1"));
2716 QAccessibleTableCellInterface *cell2Iface = child2->tableCellInterface();
2717 QCOMPARE(cell2Iface->rowIndex(), 1);
2718 QCOMPARE(cell2Iface->columnIndex(), 1);
2721 QAccessibleInterface *child3 = iface->child(11);
2722 QCOMPARE(iface->indexOfChild(child3), 12);
2723 QCOMPARE(child3->text(QAccessible::Name), QString("1.2"));
2726 QTestAccessibility::clearEvents();
2729 QAccessibleTableInterface *table2 = iface->tableInterface();
2731 QCOMPARE(table2->columnCount(), 3);
2732 QCOMPARE(table2->rowCount(), 3);
2733 QAccessibleInterface *cell1;
2734 QVERIFY(cell1 = table2->cellAt(0,0));
2735 QCOMPARE(cell1->text(QAccessible::Name), QString("0.0"));
2736 QCOMPARE(iface->indexOfChild(cell1), 6);
2738 QAccessibleInterface *cell2;
2739 QVERIFY(cell2 = table2->cellAt(0,1));
2740 QCOMPARE(cell2->text(QAccessible::Name), QString("0.1"));
2741 QCOMPARE(cell2->role(), QAccessible::Cell);
2742 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 0);
2743 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 1);
2744 QCOMPARE(iface->indexOfChild(cell2), 7);
2747 QAccessibleInterface *cell3;
2748 QVERIFY(cell3 = table2->cellAt(1,2));
2749 QCOMPARE(cell3->text(QAccessible::Name), QString("1.2"));
2750 QCOMPARE(cell3->role(), QAccessible::Cell);
2751 QCOMPARE(cell3->tableCellInterface()->rowIndex(), 1);
2752 QCOMPARE(cell3->tableCellInterface()->columnIndex(), 2);
2753 QCOMPARE(iface->indexOfChild(cell3), 12);
2756 QCOMPARE(table2->columnDescription(0), QString("h1"));
2757 QCOMPARE(table2->columnDescription(1), QString("h2"));
2758 QCOMPARE(table2->columnDescription(2), QString("h3"));
2759 QCOMPARE(table2->rowDescription(0), QString("v1"));
2760 QCOMPARE(table2->rowDescription(1), QString("v2"));
2761 QCOMPARE(table2->rowDescription(2), QString("v3"));
2767 QTestAccessibility::clearEvents();
2770 void tst_QAccessibility::calendarWidgetTest()
2772 #ifndef QT_NO_CALENDARWIDGET
2774 QCalendarWidget calendarWidget;
2776 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget);
2778 QCOMPARE(interface->role(), QAccessible::Table);
2779 QVERIFY(!interface->rect().isValid());
2780 QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
2782 calendarWidget.resize(400, 300);
2783 calendarWidget.show();
2784 #if defined(Q_OS_UNIX)
2785 QCoreApplication::processEvents();
2789 // 1 = navigationBar, 2 = view.
2790 QCOMPARE(interface->childCount(), 2);
2792 const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)),
2793 calendarWidget.size());
2794 QCOMPARE(interface->rect(), globalGeometry);
2796 QWidget *navigationBar = 0;
2797 foreach (QObject *child, calendarWidget.children()) {
2798 if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) {
2799 navigationBar = static_cast<QWidget *>(child);
2803 QVERIFY(navigationBar);
2804 QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry));
2806 QAbstractItemView *calendarView = 0;
2807 foreach (QObject *child, calendarWidget.children()) {
2808 if (child->objectName() == QLatin1String("qt_calendar_calendarview")) {
2809 calendarView = static_cast<QAbstractItemView *>(child);
2813 QVERIFY(calendarView);
2814 QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry));
2816 // Hide navigation bar.
2817 calendarWidget.setNavigationBarVisible(false);
2818 QCOMPARE(interface->childCount(), 1);
2819 QVERIFY(!navigationBar->isVisible());
2821 QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry));
2823 // Show navigation bar.
2824 calendarWidget.setNavigationBarVisible(true);
2825 QCOMPARE(interface->childCount(), 2);
2826 QVERIFY(navigationBar->isVisible());
2828 // Navigate to the navigation bar via Child.
2829 QAccessibleInterface *navigationBarInterface = interface->child(0);
2830 QVERIFY(navigationBarInterface);
2831 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2832 delete navigationBarInterface;
2833 navigationBarInterface = 0;
2835 // Navigate to the view via Child.
2836 QAccessibleInterface *calendarViewInterface = interface->child(1);
2837 QVERIFY(calendarViewInterface);
2838 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2839 delete calendarViewInterface;
2840 calendarViewInterface = 0;
2842 QVERIFY(!interface->child(-1));
2844 // Navigate from navigation bar -> view (Down).
2845 QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0);
2846 QVERIFY(calendarViewInterface);
2847 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2848 delete calendarViewInterface;
2849 calendarViewInterface = 0;
2851 // Navigate from view -> navigation bar (Up).
2852 QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0);
2853 QVERIFY(navigationBarInterface);
2854 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2855 delete navigationBarInterface;
2856 navigationBarInterface = 0;
2859 QTestAccessibility::clearEvents();
2860 #endif // QT_NO_CALENDARWIDGET
2863 void tst_QAccessibility::dockWidgetTest()
2865 #ifndef QT_NO_DOCKWIDGET
2866 // Set up a proper main window with two dock widgets
2867 QMainWindow *mw = new QMainWindow();
2868 QFrame *central = new QFrame(mw);
2869 mw->setCentralWidget(central);
2870 QMenuBar *mb = new QMenuBar(mw);
2871 mb->addAction(tr("&File"));
2874 QDockWidget *dock1 = new QDockWidget(mw);
2875 mw->addDockWidget(Qt::LeftDockWidgetArea, dock1);
2876 QPushButton *pb1 = new QPushButton(tr("Push me"), dock1);
2877 dock1->setWidget(pb1);
2879 QDockWidget *dock2 = new QDockWidget(mw);
2880 mw->addDockWidget(Qt::BottomDockWidgetArea, dock2);
2881 QPushButton *pb2 = new QPushButton(tr("Push me"), dock2);
2882 dock2->setWidget(pb2);
2884 mw->resize(600,400);
2886 #if defined(Q_OS_UNIX)
2887 QCoreApplication::processEvents();
2891 QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw);
2892 // 4 children: menu bar, dock1, dock2, and central widget
2893 QCOMPARE(accMainWindow->childCount(), 4);
2894 QAccessibleInterface *accDock1 = 0;
2895 for (int i = 0; i < 4; ++i) {
2896 accDock1 = accMainWindow->child(i);
2897 if (accMainWindow->role() == QAccessible::Window) {
2898 if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) {
2906 QCOMPARE(accDock1->role(), QAccessible::Window);
2908 QAccessibleInterface *dock1TitleBar = accDock1->child(0);
2909 QCOMPARE(dock1TitleBar->role(), QAccessible::TitleBar);
2910 QVERIFY(accDock1->rect().contains(dock1TitleBar->rect()));
2911 delete dock1TitleBar;
2913 QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
2914 globalPos.rx()+=5; //### query style
2916 QAccessibleInterface *childAt = accDock1->childAt(globalPos.x(), globalPos.y()); //###
2917 QCOMPARE(childAt->role(), QAccessible::TitleBar);
2918 int index = accDock1->indexOfChild(childAt);
2920 QAccessibleInterface *accTitleBar = accDock1->child(index - 1);
2922 QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
2923 QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);
2924 QAccessibleInterface *acc;
2925 acc = accTitleBar->parent();
2927 QCOMPARE(acc->role(), QAccessible::Window);
2937 QTestAccessibility::clearEvents();
2938 #endif // QT_NO_DOCKWIDGET
2941 void tst_QAccessibility::comboBoxTest()
2943 #if defined(Q_OS_WINCE)
2944 if (!IsValidCEPlatform())
2945 QSKIP("Test skipped on Windows Mobile test hardware");
2947 { // not editable combobox
2949 combo.addItems(QStringList() << "one" << "two" << "three");
2951 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
2952 QCOMPARE(verifyHierarchy(iface), 0);
2954 QCOMPARE(iface->role(), QAccessible::ComboBox);
2955 QCOMPARE(iface->childCount(), 1);
2958 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one"));
2960 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one"));
2961 combo.setCurrentIndex(2);
2963 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three"));
2965 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three"));
2967 QAccessibleInterface *listIface = iface->child(0);
2968 QCOMPARE(listIface->role(), QAccessible::List);
2969 QCOMPARE(listIface->childCount(), 3);
2971 QVERIFY(!combo.view()->isVisible());
2972 QVERIFY(iface->actionInterface());
2973 QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
2974 iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
2975 QVERIFY(combo.view()->isVisible());
2980 { // editable combobox
2981 QComboBox editableCombo;
2982 editableCombo.show();
2983 editableCombo.setEditable(true);
2984 editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
2986 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo);
2987 QCOMPARE(verifyHierarchy(iface), 0);
2989 QCOMPARE(iface->role(), QAccessible::ComboBox);
2990 QCOMPARE(iface->childCount(), 2);
2992 QAccessibleInterface *listIface = iface->child(0);
2993 QCOMPARE(listIface->role(), QAccessible::List);
2994 QAccessibleInterface *editIface = iface->child(1);
2995 QCOMPARE(editIface->role(), QAccessible::EditableText);
3002 QTestAccessibility::clearEvents();
3005 void tst_QAccessibility::labelTest()
3007 QString text = "Hello World";
3008 QLabel *label = new QLabel(text);
3011 #if defined(Q_OS_UNIX)
3012 QCoreApplication::processEvents();
3016 QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label);
3019 QCOMPARE(acc_label->text(QAccessible::Name), text);
3023 QTestAccessibility::clearEvents();
3025 QPixmap testPixmap(50, 50);
3029 imageLabel.setPixmap(testPixmap);
3030 imageLabel.setToolTip("Test Description");
3032 acc_label = QAccessible::queryAccessibleInterface(&imageLabel);
3035 QAccessibleImageInterface *imageInterface = acc_label->imageInterface();
3036 QVERIFY(imageInterface);
3038 QCOMPARE(imageInterface->imageSize(), testPixmap.size());
3039 QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
3040 QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
3044 QTestAccessibility::clearEvents();
3047 void tst_QAccessibility::accelerators()
3049 QWidget *window = new QWidget;
3050 QHBoxLayout *lay = new QHBoxLayout(window);
3051 QLabel *label = new QLabel(tr("&Line edit"), window);
3052 QLineEdit *le = new QLineEdit(window);
3053 lay->addWidget(label);
3055 label->setBuddy(le);
3059 QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
3060 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3061 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3062 label->setText(tr("Q &"));
3063 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3064 label->setText(tr("Q &&"));
3065 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3066 label->setText(tr("Q && A"));
3067 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3068 label->setText(tr("Q &&&A"));
3069 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3070 label->setText(tr("Q &&A"));
3071 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3073 #if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC)
3074 QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'");
3076 label->setText(tr("Q &A&B"));
3077 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3079 #if defined(Q_OS_UNIX)
3080 QCoreApplication::processEvents();
3084 QTestAccessibility::clearEvents();
3087 QTEST_MAIN(tst_QAccessibility)
3088 #include "tst_qaccessibility.moc"