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 delete childInterface;
93 if (indexFromIndexOfChild != index) {
94 qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
95 qWarning() << "Expected:" << index;
96 qWarning() << "Actual: " << indexFromIndexOfChild;
100 // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child).
101 QAccessibleInterface *navigatedChildInterface = interface->child(index - 1);
102 if (navigatedChildInterface == 0)
105 const QRect rectFromInterface = navigatedChildInterface->rect();
106 delete navigatedChildInterface;
108 // QAccessibleInterface::childAt():
109 // Calculate global child position and check that the interface
110 // returns the correct index for that position.
111 QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
112 int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y());
113 if (indexFromChildAt != index) {
114 qWarning("tst_QAccessibility::verifyChild (childAt()):");
115 qWarning() << "Expected:" << index;
116 qWarning() << "Actual: " << indexFromChildAt;
120 // QAccessibleInterface::rect():
121 // Calculate global child geometry and check that the interface
122 // returns a QRect which is equal to the calculated QRect.
123 const QRect expectedGlobalRect = QRect(globalChildPos, child->size());
124 if (expectedGlobalRect != rectFromInterface) {
125 qWarning("tst_QAccessibility::verifyChild (rect()):");
126 qWarning() << "Expected:" << expectedGlobalRect;
127 qWarning() << "Actual: " << rectFromInterface;
131 // Verify that the child is within its domain.
132 if (!domain.contains(rectFromInterface)) {
133 qWarning("tst_QAccessibility::verifyChild: Child is not within its domain.");
140 static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget)
142 if (!parentInterface || !childWidget)
144 QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(childWidget);
147 int index = parentInterface->indexOfChild(childInterface);
148 delete childInterface;
152 #define EXPECT(cond) \
154 if (!errorAt && !(cond)) { \
155 errorAt = __LINE__; \
156 qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
160 static int verifyHierarchy(QAccessibleInterface *iface)
163 static int treelevel = 0; // for error diagnostics
164 QAccessibleInterface *middleChild, *if2;
167 int middle = iface->childCount()/2 + 1;
168 if (iface->childCount() >= 2) {
169 middleChild = iface->child(middle - 1);
171 for (int i = 0; i < iface->childCount() && !errorAt; ++i) {
172 if2 = iface->child(i);
174 // navigate Ancestor...
175 QAccessibleInterface *parent = if2->parent();
176 EXPECT(iface->object() == parent->object());
179 // navigate Sibling...
180 // if (middleChild) {
181 // entry = if2->navigate(QAccessible::Sibling, middle, &if3);
182 // EXPECT(entry == 0 && if3->object() == middleChild->object());
185 // EXPECT(iface->indexOfChild(middleChild) == middle);
188 // verify children...
190 errorAt = verifyHierarchy(if2);
199 QRect childRect(QAccessibleInterface *iface, int index = 0)
201 QAccessibleInterface *child = iface->child(index);
202 QRect rect = child->rect();
207 class tst_QAccessibility : public QObject
211 tst_QAccessibility();
212 virtual ~tst_QAccessibility();
216 void cleanupTestCase();
222 void deletedWidget();
224 void navigateGeometric();
225 void navigateHierarchy();
227 void navigateCovered();
228 void textAttributes();
233 void applicationTest();
234 void mainWindowTest();
236 void scrollBarTest();
238 void tabWidgetTest();
241 void doubleSpinBoxTest();
243 void textBrowserTest();
245 void mdiSubWindowTest();
247 void workspaceTest();
248 void dialogButtonBoxTest();
250 void rubberBandTest();
251 void abstractScrollAreaTest();
252 void scrollAreaTest();
258 void calendarWidgetTest();
259 void dockWidgetTest();
261 void accessibleName();
271 const double Q_PI = 3.14159265358979323846;
273 QString eventName(const int ev)
276 case 0x0001: return "SoundPlayed";
277 case 0x0002: return "Alert";
278 case 0x0003: return "ForegroundChanged";
279 case 0x0004: return "MenuStart";
280 case 0x0005: return "MenuEnd";
281 case 0x0006: return "PopupMenuStart";
282 case 0x0007: return "PopupMenuEnd";
283 case 0x000C: return "ContextHelpStart";
284 case 0x000D: return "ContextHelpEnd";
285 case 0x000E: return "DragDropStart";
286 case 0x000F: return "DragDropEnd";
287 case 0x0010: return "DialogStart";
288 case 0x0011: return "DialogEnd";
289 case 0x0012: return "ScrollingStart";
290 case 0x0013: return "ScrollingEnd";
291 case 0x0018: return "MenuCommand";
293 case 0x0116: return "TableModelChanged";
294 case 0x011B: return "TextCaretMoved";
296 case 0x8000: return "ObjectCreated";
297 case 0x8001: return "ObjectDestroyed";
298 case 0x8002: return "ObjectShow";
299 case 0x8003: return "ObjectHide";
300 case 0x8004: return "ObjectReorder";
301 case 0x8005: return "Focus";
302 case 0x8006: return "Selection";
303 case 0x8007: return "SelectionAdd";
304 case 0x8008: return "SelectionRemove";
305 case 0x8009: return "SelectionWithin";
306 case 0x800A: return "StateChanged";
307 case 0x800B: return "LocationChanged";
308 case 0x800C: return "NameChanged";
309 case 0x800D: return "DescriptionChanged";
310 case 0x800E: return "ValueChanged";
311 case 0x800F: return "ParentChanged";
312 case 0x80A0: return "HelpChanged";
313 case 0x80B0: return "DefaultActionChanged";
314 case 0x80C0: return "AcceleratorChanged";
315 default: return "Unknown Event";
319 QAccessible::State state(QWidget * const widget)
321 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
323 qWarning() << "Cannot get QAccessibleInterface for widget";
324 QAccessible::State state = (iface ? iface->state() : static_cast<QAccessible::State>(0));
329 class QtTestAccessibleWidget: public QWidget
333 QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
337 pal.setColor(backgroundRole(), Qt::black);//black is beautiful
343 class QtTestAccessibleWidgetIface: public QAccessibleWidget
346 QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
347 QString text(QAccessible::Text t) const
349 if (t == QAccessible::Help)
350 return QString::fromLatin1("Help yourself");
351 return QAccessibleWidget::text(t);
353 static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
355 if (key == "QtTestAccessibleWidget")
356 return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
361 tst_QAccessibility::tst_QAccessibility()
366 tst_QAccessibility::~tst_QAccessibility()
370 void tst_QAccessibility::onClicked()
375 void tst_QAccessibility::initTestCase()
377 QTestAccessibility::initialize();
378 QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
381 void tst_QAccessibility::cleanupTestCase()
383 QTestAccessibility::cleanup();
386 void tst_QAccessibility::init()
388 QTestAccessibility::clearEvents();
391 void tst_QAccessibility::cleanup()
393 const EventList list = QTestAccessibility::events();
394 if (!list.isEmpty()) {
395 qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
396 QString(QTest::currentTestFunction()).toAscii().constData());
397 for (int i = 0; i < list.count(); ++i)
398 qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
399 eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
401 QTestAccessibility::clearEvents();
404 void tst_QAccessibility::eventTest()
406 QPushButton* button = new QPushButton(0);
407 button->setObjectName(QString("Olaf"));
410 QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
411 button->setFocus(Qt::MouseFocusReason);
412 QTestAccessibility::clearEvents();
413 QTest::mouseClick(button, Qt::LeftButton, 0);
414 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
415 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
417 button->setAccessibleName("Olaf the second");
418 QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
419 button->setAccessibleDescription("This is a button labeled Olaf");
420 QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
423 QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
428 void tst_QAccessibility::customWidget()
430 QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
432 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
434 QVERIFY(iface->isValid());
435 QCOMPARE(iface->object(), (QObject*)widget);
436 QCOMPARE(iface->object()->objectName(), QString("Heinz"));
437 QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
443 void tst_QAccessibility::deletedWidget()
445 QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
446 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
448 QVERIFY(iface->isValid());
449 QCOMPARE(iface->object(), (QObject*)widget);
453 QVERIFY(!iface->isValid());
457 void tst_QAccessibility::navigateGeometric()
460 static const int skip = 20; //speed the test up significantly
461 static const double step = Q_PI / 180;
462 QWidget *w = new QWidget(0);
463 w->setObjectName(QString("Josef"));
464 w->setFixedSize(400, 400);
467 QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol");
468 center->move(200, 200);
470 // arrange 360 widgets around it in a circle
471 QtTestAccessibleWidget *aw = 0;
472 for (int i = 0; i < 360; i += skip) {
473 aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1());
474 aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) );
477 aw = new QtTestAccessibleWidget(w, "Earth");
478 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center);
479 QAccessibleInterface *target = 0;
481 QVERIFY(iface->isValid());
484 QCoreApplication::processEvents();
487 // let one widget rotate around center
488 for (int i = 0; i < 360; i+=skip) {
489 aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) );
491 if (i < 45 || i > 315) {
492 QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
493 } else if ( i < 135 ) {
494 QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
495 } else if ( i < 225 ) {
496 QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
498 QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
502 QVERIFY(target->isValid());
503 QVERIFY(target->object());
504 QCOMPARE(target->object()->objectName(), aw->objectName());
505 delete target; target = 0;
508 // test invisible widget
509 target = QAccessible::queryAccessibleInterface(aw);
510 QVERIFY(!(target->state() & QAccessible::Invisible));
512 QVERIFY(target->state() & QAccessible::Invisible);
513 delete target; target = 0;
515 aw->move(center->x() + 10, center->y());
516 QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
518 QVERIFY(target->isValid());
519 QVERIFY(target->object());
520 QVERIFY(QString(target->object()->objectName()) != "Earth");
521 delete target; target = 0;
523 aw->move(center->x() - 10, center->y());
524 QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
526 QVERIFY(target->isValid());
527 QVERIFY(target->object());
528 QVERIFY(QString(target->object()->objectName()) != "Earth");
529 delete target; target = 0;
531 aw->move(center->x(), center->y() + 10);
532 QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
534 QVERIFY(target->isValid());
535 QVERIFY(target->object());
536 QVERIFY(QString(target->object()->objectName()) != "Earth");
537 delete target; target = 0;
539 aw->move(center->x(), center->y() - 10);
540 QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
542 QVERIFY(target->isValid());
543 QVERIFY(target->object());
544 QVERIFY(QString(target->object()->objectName()) != "Earth");
545 delete target; target = 0;
550 QTestAccessibility::clearEvents();
553 void tst_QAccessibility::sliderTest()
556 QSlider *slider = new QSlider(0);
557 slider->setObjectName(QString("Slidy"));
559 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider);
561 QVERIFY(iface->isValid());
563 QCOMPARE(iface->childCount(), 0);
564 QCOMPARE(iface->role(), QAccessible::Slider);
566 QAccessibleValueInterface *valueIface = iface->valueInterface();
567 QVERIFY(valueIface != 0);
568 QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum());
569 QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum());
570 slider->setValue(50);
571 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
573 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
574 slider->setValue(100);
575 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
576 valueIface->setCurrentValue(77);
577 QCOMPARE(77, slider->value());
582 QTestAccessibility::clearEvents();
585 void tst_QAccessibility::navigateCovered()
588 QWidget *w = new QWidget(0);
589 w->setObjectName(QString("Harry"));
590 QWidget *w1 = new QWidget(w);
591 w1->setObjectName(QString("1"));
592 QWidget *w2 = new QWidget(w);
593 w2->setObjectName(QString("2"));
595 #if defined(Q_OS_UNIX)
596 QCoreApplication::processEvents();
600 w->setFixedSize(6, 6);
601 w1->setFixedSize(5, 5);
602 w2->setFixedSize(5, 5);
606 QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1);
607 QVERIFY(iface1 != 0);
608 QVERIFY(iface1->isValid());
609 QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2);
610 QVERIFY(iface2 != 0);
611 QVERIFY(iface2->isValid());
612 QAccessibleInterface *iface3 = 0;
614 QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1);
615 QVERIFY(iface3 == 0);
616 QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1);
617 QVERIFY(iface3 == 0);
618 QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1);
619 QVERIFY(iface3 == 0);
621 for (int loop = 0; loop < 2; ++loop) {
622 for (int x = 0; x < w->width(); ++x) {
623 for (int y = 0; y < w->height(); ++y) {
625 if (w1->geometry().intersects(w2->geometry())) {
626 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
627 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
628 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0);
629 QVERIFY(iface3 != 0);
630 QVERIFY(iface3->isValid());
631 QCOMPARE(iface3->object(), iface2->object());
632 delete iface3; iface3 = 0;
633 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0);
634 QVERIFY(iface3 != 0);
635 QVERIFY(iface3->isValid());
636 QCOMPARE(iface3->object(), iface1->object());
637 delete iface3; iface3 = 0;
639 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
640 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
641 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1);
642 QVERIFY(iface3 == 0);
643 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
644 QVERIFY(iface3 == 0);
645 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
646 QVERIFY(iface3 == 0);
647 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1);
648 QVERIFY(iface3 == 0);
653 // switch children for second loop
655 QAccessibleInterface *temp = iface1;
660 delete iface1; iface1 = 0;
661 delete iface2; iface2 = 0;
662 iface1 = QAccessible::queryAccessibleInterface(w1);
663 QVERIFY(iface1 != 0);
664 QVERIFY(iface1->isValid());
665 iface2 = QAccessible::queryAccessibleInterface(w2);
666 QVERIFY(iface2 != 0);
667 QVERIFY(iface2->isValid());
672 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
673 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
674 QVERIFY(!(iface1->state() & QAccessible::Invisible));
676 QVERIFY(iface1->state() & QAccessible::Invisible);
677 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
678 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
679 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
680 QVERIFY(iface3 == 0);
681 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
682 QVERIFY(iface3 == 0);
684 delete iface1; iface1 = 0;
685 delete iface2; iface2 = 0;
688 QTestAccessibility::clearEvents();
691 void tst_QAccessibility::navigateHierarchy()
694 QWidget *w = new QWidget(0);
695 w->setObjectName(QString("Hans"));
697 QWidget *w1 = new QWidget(w);
698 w1->setObjectName(QString("1"));
700 QWidget *w2 = new QWidget(w);
701 w2->setObjectName(QString("2"));
703 QWidget *w3 = new QWidget(w);
704 w3->setObjectName(QString("3"));
706 QWidget *w31 = new QWidget(w3);
707 w31->setObjectName(QString("31"));
710 QAccessibleInterface *target = 0;
711 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w);
713 QVERIFY(iface->isValid());
715 QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1);
716 QVERIFY(target == 0);
717 QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1);
718 QVERIFY(target == 0);
720 target = iface->child(14);
721 QVERIFY(target == 0);
722 target = iface->child(-1);
723 QVERIFY(target == 0);
724 target = iface->child(0);
725 QAccessibleInterface *interfaceW1 = iface->child(0);
727 QVERIFY(target->isValid());
728 QCOMPARE(target->object(), (QObject*)w1);
729 QVERIFY(interfaceW1 != 0);
730 QVERIFY(interfaceW1->isValid());
731 QCOMPARE(interfaceW1->object(), (QObject*)w1);
733 delete iface; iface = 0;
735 QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1);
737 QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1);
739 QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1);
741 QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0);
743 QVERIFY(iface->isValid());
744 QCOMPARE(iface->object(), (QObject*)w2);
745 delete target; target = 0;
746 QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0);
747 QVERIFY(target != 0);
748 QVERIFY(target->isValid());
749 QCOMPARE(target->object(), (QObject*)w3);
750 delete iface; iface = 0;
752 iface = target->child(0);
754 QVERIFY(iface->isValid());
755 QCOMPARE(iface->object(), (QObject*)w31);
756 delete target; target = 0;
758 QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1);
759 QVERIFY(target == 0);
760 QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1);
761 QVERIFY(target == 0);
762 QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0);
763 QVERIFY(target != 0);
764 QVERIFY(target->isValid());
765 QCOMPARE(target->object(), (QObject*)w31);
766 delete iface; iface = 0;
768 iface = target->parent();
770 QVERIFY(iface->isValid());
771 QCOMPARE(iface->object(), (QObject*)w3);
772 delete iface; iface = 0;
773 delete target; target = 0;
777 QTestAccessibility::clearEvents();
780 #define QSETCOMPARE(thetypename, elements, otherelements) \
781 QCOMPARE((QSet<thetypename>() << elements), (QSet<thetypename>() << otherelements))
783 static QWidget *createWidgets()
785 QWidget *w = new QWidget();
787 QHBoxLayout *box = new QHBoxLayout(w);
790 box->addWidget(new QComboBox(w));
791 box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
792 box->addWidget(new QHeaderView(Qt::Vertical, w));
793 box->addWidget(new QTreeView(w));
794 box->addWidget(new QTreeWidget(w));
795 box->addWidget(new QListView(w));
796 box->addWidget(new QListWidget(w));
797 box->addWidget(new QTableView(w));
798 box->addWidget(new QTableWidget(w));
799 box->addWidget(new QCalendarWidget(w));
800 box->addWidget(new QDialogButtonBox(w));
801 box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
802 box->addWidget(new QFrame(w));
803 box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
804 box->addWidget(new QProgressBar(w));
805 box->addWidget(new QTabWidget(w));
806 box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
807 box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
808 box->addWidget(new QDial(w));
809 box->addWidget(new QScrollBar(w));
810 box->addWidget(new QSlider(w));
811 box->addWidget(new QDateTimeEdit(w));
812 box->addWidget(new QDoubleSpinBox(w));
813 box->addWidget(new QSpinBox(w));
814 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
815 box->addWidget(new QLCDNumber(w));
816 box->addWidget(new QStackedWidget(w));
817 box->addWidget(new QToolBox(w));
818 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
819 box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
822 * QAbstractItemView, QGraphicsView, QScrollArea,
823 * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
824 * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
829 void tst_QAccessibility::accessibleName()
831 QWidget *toplevel = createWidgets();
833 #if defined(Q_OS_UNIX)
834 QCoreApplication::processEvents();
837 QLayout *lout = toplevel->layout();
838 for (int i = 0; i < lout->count(); i++) {
839 QLayoutItem *item = lout->itemAt(i);
840 QWidget *child = item->widget();
842 QString name = tr("Widget Name %1").arg(i);
843 child->setAccessibleName(name);
844 QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
845 QCOMPARE(acc->text(QAccessible::Name), name);
847 QString desc = tr("Widget Description %1").arg(i);
848 child->setAccessibleDescription(desc);
849 QCOMPARE(acc->text(QAccessible::Description), desc);
854 QTestAccessibility::clearEvents();
857 void tst_QAccessibility::textAttributes()
863 QString text("<html><head></head><body>"
864 "Hello, <b>this</b> is an <i><b>example</b> text</i>."
865 "<span style=\"font-family: monospace\">Multiple fonts are used.</span>"
866 "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used."
867 "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."
870 textEdit.setText(text);
871 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit);
873 QAccessibleTextInterface *textInterface=interface->textInterface();
875 QVERIFY(textInterface);
876 QCOMPARE(textInterface->characterCount(), 112);
878 attributes = textInterface->attributes(10, &startOffset, &endOffset);
879 QCOMPARE(startOffset, 7);
880 QCOMPARE(endOffset, 11);
881 attributes.prepend(';');
882 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
884 attributes = textInterface->attributes(18, &startOffset, &endOffset);
885 QCOMPARE(startOffset, 18);
886 QCOMPARE(endOffset, 25);
887 attributes.prepend(';');
888 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
889 QVERIFY(attributes.contains(QLatin1String(";font-style:italic;")));
891 attributes = textInterface->attributes(34, &startOffset, &endOffset);
892 QCOMPARE(startOffset, 31);
893 QCOMPARE(endOffset, 55);
894 attributes.prepend(';');
895 QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";")));
897 attributes = textInterface->attributes(65, &startOffset, &endOffset);
898 QCOMPARE(startOffset, 64);
899 QCOMPARE(endOffset, 74);
900 attributes.prepend(';');
901 QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;")));
903 attributes = textInterface->attributes(110, &startOffset, &endOffset);
904 QCOMPARE(startOffset, 109);
905 QCOMPARE(endOffset, 111);
906 attributes.prepend(';');
907 QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);")));
908 QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);")));
911 void tst_QAccessibility::hideShowTest()
913 QWidget * const window = new QWidget();
914 QWidget * const child = new QWidget(window);
916 QVERIFY(state(window) & QAccessible::Invisible);
917 QVERIFY(state(child) & QAccessible::Invisible);
919 QTestAccessibility::clearEvents();
921 // show() and veryfy that both window and child are not invisible and get ObjectShow events.
923 QVERIFY(state(window) ^ QAccessible::Invisible);
924 QVERIFY(state(child) ^ QAccessible::Invisible);
925 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
926 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
927 QTestAccessibility::clearEvents();
929 // hide() and veryfy that both window and child are invisible and get ObjectHide events.
931 QVERIFY(state(window) & QAccessible::Invisible);
932 QVERIFY(state(child) & QAccessible::Invisible);
933 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
934 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
935 QTestAccessibility::clearEvents();
938 QTestAccessibility::clearEvents();
942 void tst_QAccessibility::actionTest()
945 QCOMPARE(QAccessibleActionInterface::pressAction(), QString(QStringLiteral("Press")));
947 QWidget *widget = new QWidget;
948 widget->setFocusPolicy(Qt::NoFocus);
951 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(widget);
953 QVERIFY(interface->isValid());
954 QAccessibleActionInterface *actions = interface->actionInterface();
957 // no actions by default, except when focusable
958 QCOMPARE(actions->actionNames(), QStringList());
959 widget->setFocusPolicy(Qt::StrongFocus);
960 QCOMPARE(actions->actionNames(), QStringList(QAccessibleActionInterface::setFocusAction()));
965 QTestAccessibility::clearEvents();
968 QPushButton *button = new QPushButton;
970 button->clearFocus();
971 QCOMPARE(button->hasFocus(), false);
972 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
973 QAccessibleActionInterface *actions = interface->actionInterface();
976 // Make sure the "primary action" press comes first!
977 QCOMPARE(actions->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
979 actions->doAction(QAccessibleActionInterface::setFocusAction());
981 QCOMPARE(button->hasFocus(), true);
983 connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
984 QCOMPARE(click_count, 0);
985 actions->doAction(QAccessibleActionInterface::pressAction());
987 QCOMPARE(click_count, 1);
992 QTestAccessibility::clearEvents();
995 void tst_QAccessibility::applicationTest()
997 QLatin1String name = QLatin1String("My Name");
998 qApp->setApplicationName(name);
999 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp);
1000 QCOMPARE(interface->text(QAccessible::Name), name);
1001 QCOMPARE(interface->role(), QAccessible::Application);
1005 void tst_QAccessibility::mainWindowTest()
1007 QMainWindow *mw = new QMainWindow;
1008 mw->resize(300, 200);
1009 mw->show(); // triggers layout
1011 QLatin1String name = QLatin1String("I am the main window");
1012 mw->setWindowTitle(name);
1013 QTest::qWaitForWindowShown(mw);
1014 QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
1016 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
1017 QCOMPARE(interface->text(QAccessible::Name), name);
1018 QCOMPARE(interface->role(), QAccessible::Window);
1021 QTestAccessibility::clearEvents();
1024 class CounterButton : public QPushButton {
1027 CounterButton(const QString& name, QWidget* parent)
1028 : QPushButton(name, parent), clickCount(0)
1030 connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount()));
1034 void incClickCount() {
1039 void tst_QAccessibility::buttonTest()
1042 window.setLayout(new QVBoxLayout);
1044 // Standard push button
1045 CounterButton pushButton("Ok", &window);
1048 QPushButton toggleButton("Toggle", &window);
1049 toggleButton.setCheckable(true);
1051 // standard checkbox
1052 QCheckBox checkBox("Check me!", &window);
1054 // tristate checkbox
1055 QCheckBox tristate("Tristate!", &window);
1056 tristate.setTristate(TRUE);
1059 QRadioButton radio("Radio me!", &window);
1061 // standard toolbutton
1062 QToolButton toolbutton(&window);
1063 toolbutton.setText("Tool");
1064 toolbutton.setMinimumSize(20,20);
1066 // standard toolbutton
1067 QToolButton toggletool(&window);
1068 toggletool.setCheckable(true);
1069 toggletool.setText("Toggle");
1070 toggletool.setMinimumSize(20,20);
1073 QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton);
1074 QAccessibleActionInterface* actionInterface = interface->actionInterface();
1075 QVERIFY(actionInterface != 0);
1076 QCOMPARE(interface->role(), QAccessible::PushButton);
1078 // buttons only have a click action
1079 QCOMPARE(actionInterface->actionNames().size(), 2);
1080 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
1081 QCOMPARE(pushButton.clickCount, 0);
1082 actionInterface->doAction(QAccessibleActionInterface::pressAction());
1084 QCOMPARE(pushButton.clickCount, 1);
1087 // test toggle button
1088 interface = QAccessible::queryAccessibleInterface(&toggleButton);
1089 actionInterface = interface->actionInterface();
1090 QCOMPARE(interface->role(), QAccessible::CheckBox);
1091 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1092 QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
1093 QVERIFY(!toggleButton.isChecked());
1094 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1095 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1097 QVERIFY(toggleButton.isChecked());
1098 QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
1099 QVERIFY(interface->state() & QAccessible::Checked);
1103 // test menu push button
1104 QAction *foo = new QAction("Foo", 0);
1105 foo->setShortcut(QKeySequence("Ctrl+F"));
1106 QMenu *menu = new QMenu();
1107 menu->addAction(foo);
1108 QPushButton menuButton;
1109 menuButton.setMenu(menu);
1111 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
1112 QCOMPARE(interface->role(), QAccessible::ButtonMenu);
1113 QVERIFY(interface->state() & QAccessible::HasPopup);
1114 QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction());
1115 // showing the menu enters a new event loop...
1116 // interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1117 // QTest::qWait(500);
1123 interface = QAccessible::queryAccessibleInterface(&checkBox);
1124 actionInterface = interface->actionInterface();
1125 QCOMPARE(interface->role(), QAccessible::CheckBox);
1126 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1127 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1128 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1130 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
1131 QVERIFY(interface->state() & QAccessible::Checked);
1132 QVERIFY(checkBox.isChecked());
1136 interface = QAccessible::queryAccessibleInterface(&radio);
1137 actionInterface = interface->actionInterface();
1138 QCOMPARE(interface->role(), QAccessible::RadioButton);
1139 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1140 QVERIFY((interface->state() & QAccessible::Checked) == 0);
1141 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1143 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1144 QVERIFY(interface->state() & QAccessible::Checked);
1145 QVERIFY(checkBox.isChecked());
1148 // // test standard toolbutton
1149 // QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
1150 // QCOMPARE(test->role(), QAccessible::PushButton);
1151 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1152 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1153 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1156 // // toggle tool button
1157 // QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test));
1158 // QCOMPARE(test->role(), QAccessible::CheckBox);
1159 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1160 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check"));
1161 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1162 // QVERIFY(test->doAction(QAccessible::Press, 0));
1163 // QTest::qWait(500);
1164 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck"));
1165 // QCOMPARE(test->state(), (int)QAccessible::Checked);
1168 // // test menu toolbutton
1169 // QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test));
1170 // QCOMPARE(test->role(), QAccessible::ButtonMenu);
1171 // QCOMPARE(test->defaultAction(0), 1);
1172 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open"));
1173 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1174 // QCOMPARE(test->actionCount(0), 1);
1175 // QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
1178 // // test split menu toolbutton
1179 // QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
1180 // QCOMPARE(test->childCount(), 2);
1181 // QCOMPARE(test->role(), QAccessible::ButtonDropDown);
1182 // QCOMPARE(test->role(1), QAccessible::PushButton);
1183 // QCOMPARE(test->role(2), QAccessible::ButtonMenu);
1184 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1185 // QCOMPARE(test->defaultAction(1), QAccessible::Press);
1186 // QCOMPARE(test->defaultAction(2), QAccessible::Press);
1187 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1188 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1189 // QCOMPARE(test->actionCount(0), 1);
1190 // QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open"));
1191 // QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press"));
1192 // QCOMPARE(test->state(1), (int)QAccessible::Normal);
1193 // QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
1194 // QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
1197 QTestAccessibility::clearEvents();
1200 void tst_QAccessibility::scrollBarTest()
1202 QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
1203 QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
1204 QVERIFY(scrollBarInterface);
1205 QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
1206 scrollBar->resize(200, 50);
1208 QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible);
1209 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
1210 QTestAccessibility::clearEvents();
1213 QVERIFY(scrollBarInterface->state() & QAccessible::Invisible);
1214 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
1215 QTestAccessibility::clearEvents();
1217 // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
1219 scrollBar->setMinimum(11);
1220 scrollBar->setMaximum(111);
1222 QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface();
1223 QVERIFY(valueIface != 0);
1224 QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum());
1225 QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum());
1226 scrollBar->setValue(50);
1227 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1228 scrollBar->setValue(0);
1229 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1230 scrollBar->setValue(100);
1231 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1232 valueIface->setCurrentValue(77);
1233 QCOMPARE(77, scrollBar->value());
1235 const QRect scrollBarRect = scrollBarInterface->rect();
1236 QVERIFY(scrollBarRect.isValid());
1238 delete scrollBarInterface;
1241 QTestAccessibility::clearEvents();
1244 void tst_QAccessibility::tabTest()
1246 QTabBar *tabBar = new QTabBar();
1249 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar);
1251 QCOMPARE(interface->childCount(), 2);
1253 // Test that the Invisible bit for the navigation buttons gets set
1254 // and cleared correctly.
1255 QAccessibleInterface *leftButton = interface->child(0);
1256 QCOMPARE(leftButton->role(), QAccessible::PushButton);
1257 QVERIFY(leftButton->state() & QAccessible::Invisible);
1261 for (int i = 0; i < lots; ++i)
1262 tabBar->addTab("Foo");
1264 QAccessibleInterface *child1 = interface->child(0);
1265 QAccessibleInterface *child2 = interface->child(1);
1267 QCOMPARE(child1->role(), QAccessible::PageTab);
1269 QCOMPARE(child2->role(), QAccessible::PageTab);
1271 QVERIFY((child1->state() & QAccessible::Invisible) == false);
1274 QCoreApplication::processEvents();
1277 QVERIFY(child1->state() & QAccessible::Invisible);
1280 tabBar->setCurrentIndex(0);
1282 // Test that sending a focus action to a tab does not select it.
1283 // child2->doAction(QAccessible::Focus, 2, QVariantList());
1284 QCOMPARE(tabBar->currentIndex(), 0);
1286 // Test that sending a press action to a tab selects it.
1287 QVERIFY(child2->actionInterface());
1288 QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1289 QCOMPARE(tabBar->currentIndex(), 0);
1290 child2->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
1291 QCOMPARE(tabBar->currentIndex(), 1);
1297 QTestAccessibility::clearEvents();
1300 void tst_QAccessibility::tabWidgetTest()
1302 QTabWidget *tabWidget = new QTabWidget();
1305 // the interface for the tab is just a container for tabbar and stacked widget
1306 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget);
1308 QCOMPARE(interface->childCount(), 2);
1309 QCOMPARE(interface->role(), QAccessible::Client);
1311 // Create pages, check navigation
1312 QLabel *label1 = new QLabel("Page 1", tabWidget);
1313 tabWidget->addTab(label1, "Tab 1");
1314 QLabel *label2 = new QLabel("Page 2", tabWidget);
1315 tabWidget->addTab(label2, "Tab 2");
1317 QCOMPARE(interface->childCount(), 2);
1319 QAccessibleInterface* tabBarInterface = 0;
1320 // there is no special logic to sort the children, so the contents will be 1, the tab bar 2
1321 tabBarInterface = interface->child(1);
1322 QVERIFY(tabBarInterface);
1323 QCOMPARE(tabBarInterface->childCount(), 4);
1324 QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList);
1326 QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0);
1327 QVERIFY(tabButton1Interface);
1328 QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab);
1329 QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1"));
1331 QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1);
1332 QVERIFY(tabButton1Interface);
1333 QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab);
1334 QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2"));
1336 QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2);
1337 QVERIFY(tabButtonLeft);
1338 QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton);
1339 QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left"));
1341 QAccessibleInterface* tabButtonRight = tabBarInterface->child(3);
1342 QVERIFY(tabButtonRight);
1343 QCOMPARE(tabButtonRight->role(), QAccessible::PushButton);
1344 QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right"));
1345 delete tabButton1Interface;
1346 delete tabButton2Interface;
1347 delete tabButtonLeft;
1348 delete tabButtonRight;
1350 QAccessibleInterface* stackWidgetInterface = interface->child(0);
1351 QVERIFY(stackWidgetInterface);
1352 QCOMPARE(stackWidgetInterface->childCount(), 2);
1353 QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane);
1355 QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0);
1356 QVERIFY(stackChild1Interface);
1358 QCOMPARE(stackChild1Interface->childCount(), 0);
1360 QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText);
1361 QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1"));
1362 QCOMPARE(label1, stackChild1Interface->object());
1364 // Navigation in stack widgets should be consistent
1365 QAccessibleInterface* parent = stackChild1Interface->parent();
1368 QCOMPARE(parent->childCount(), 2);
1370 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1373 QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1);
1374 QVERIFY(stackChild2Interface);
1375 QCOMPARE(stackChild2Interface->childCount(), 0);
1376 QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText);
1377 QCOMPARE(label2, stackChild2Interface->object());
1378 QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name));
1380 parent = stackChild2Interface->parent();
1383 QCOMPARE(parent->childCount(), 2);
1385 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1388 delete tabBarInterface;
1389 delete stackChild1Interface;
1390 delete stackChild2Interface;
1391 delete stackWidgetInterface;
1394 QTestAccessibility::clearEvents();
1397 void tst_QAccessibility::menuTest()
1401 mw.resize(300, 200);
1402 QMenu *file = mw.menuBar()->addMenu("&File");
1403 QMenu *fileNew = file->addMenu("&New...");
1404 fileNew->menuAction()->setShortcut(tr("Ctrl+N"));
1405 fileNew->addAction("Text file");
1406 fileNew->addAction("Image file");
1407 file->addAction("&Open")->setShortcut(tr("Ctrl+O"));
1408 file->addAction("&Save")->setShortcut(tr("Ctrl+S"));
1409 file->addSeparator();
1410 file->addAction("E&xit")->setShortcut(tr("Alt+F4"));
1412 QMenu *edit = mw.menuBar()->addMenu("&Edit");
1413 edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z"));
1414 edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y"));
1415 edit->addSeparator();
1416 edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X"));
1417 edit->addAction("&Copy")->setShortcut(tr("Ctrl+C"));
1418 edit->addAction("&Paste")->setShortcut(tr("Ctrl+V"));
1419 edit->addAction("&Delete")->setShortcut(tr("Del"));
1420 edit->addSeparator();
1421 edit->addAction("Pr&operties");
1423 mw.menuBar()->addSeparator();
1425 QMenu *help = mw.menuBar()->addMenu("&Help");
1426 help->addAction("&Contents");
1427 help->addAction("&About");
1429 mw.menuBar()->addAction("Action!");
1431 mw.show(); // triggers layout
1434 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
1435 QCOMPARE(verifyHierarchy(interface), 0);
1438 QCOMPARE(interface->childCount(), 5);
1439 QCOMPARE(interface->role(), QAccessible::MenuBar);
1441 QAccessibleInterface *iFile = interface->child(0);
1442 QAccessibleInterface *iEdit = interface->child(1);
1443 QAccessibleInterface *iSeparator = interface->child(2);
1444 QAccessibleInterface *iHelp = interface->child(3);
1445 QAccessibleInterface *iAction = interface->child(4);
1447 QCOMPARE(iFile->role(), QAccessible::MenuItem);
1448 QCOMPARE(iEdit->role(), QAccessible::MenuItem);
1449 QCOMPARE(iSeparator->role(), QAccessible::Separator);
1450 QCOMPARE(iHelp->role(), QAccessible::MenuItem);
1451 QCOMPARE(iAction->role(), QAccessible::MenuItem);
1454 if (!IsValidCEPlatform())
1455 QSKIP("Tests do not work on Mobile platforms due to native menus");
1457 QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft());
1458 QCOMPARE(interface->rect().size(), mw.menuBar()->size());
1460 QVERIFY(interface->rect().contains(iFile->rect()));
1461 QVERIFY(interface->rect().contains(iEdit->rect()));
1462 // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible
1463 QVERIFY(interface->rect().contains(iHelp->rect()));
1464 QVERIFY(interface->rect().contains(iAction->rect()));
1467 QCOMPARE(iFile->text(QAccessible::Name), QString("File"));
1468 QCOMPARE(iEdit->text(QAccessible::Name), QString("Edit"));
1469 QCOMPARE(iSeparator->text(QAccessible::Name), QString());
1470 QCOMPARE(iHelp->text(QAccessible::Name), QString("Help"));
1471 QCOMPARE(iAction->text(QAccessible::Name), QString("Action!"));
1473 // TODO: Currently not working, task to fix is #100019.
1475 QCOMPARE(iFile->text(QAccessible::Accelerator), tr("Alt+F"));
1476 QCOMPARE(iEdit->text(QAccessible::Accelerator), tr("Alt+E"));
1477 QCOMPARE(iSeparator->text(QAccessible::Accelerator), QString());
1478 QCOMPARE(iHelp->text(QAccessible::Accelerator), tr("Alt+H"));
1479 QCOMPARE(iAction->text(QAccessible::Accelerator), QString());
1482 QVERIFY(iFile->actionInterface());
1484 QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1485 QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList());
1486 QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1487 QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1489 bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu);
1490 int menuFadeDelay = 300;
1491 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1493 QTest::qWait(menuFadeDelay);
1494 QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible());
1495 iEdit->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1497 QTest::qWait(menuFadeDelay);
1498 QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible());
1499 iHelp->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1501 QTest::qWait(menuFadeDelay);
1502 QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible());
1503 iAction->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1505 QTest::qWait(menuFadeDelay);
1506 QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible());
1508 QVERIFY(interface->actionInterface());
1509 QCOMPARE(interface->actionInterface()->actionNames(), QStringList());
1511 interface = QAccessible::queryAccessibleInterface(file);
1512 QCOMPARE(interface->childCount(), 5);
1513 QCOMPARE(interface->role(), QAccessible::PopupMenu);
1515 QAccessibleInterface *iFileNew = interface->child(0);
1516 QAccessibleInterface *iFileOpen = interface->child(1);
1517 QAccessibleInterface *iFileSave = interface->child(2);
1518 QAccessibleInterface *iFileSeparator = interface->child(3);
1519 QAccessibleInterface *iFileExit = interface->child(4);
1521 QCOMPARE(iFileNew->role(), QAccessible::MenuItem);
1522 QCOMPARE(iFileOpen->role(), QAccessible::MenuItem);
1523 QCOMPARE(iFileSave->role(), QAccessible::MenuItem);
1524 QCOMPARE(iFileSeparator->role(), QAccessible::Separator);
1525 QCOMPARE(iFileExit->role(), QAccessible::MenuItem);
1526 QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1527 QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1528 QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1529 QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList());
1530 QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1532 QAccessibleInterface *iface = 0;
1533 QAccessibleInterface *iface2 = 0;
1535 // traverse siblings with navigate(Sibling, ...)
1537 iface = interface->child(0);
1539 QCOMPARE(iface->role(), QAccessible::MenuItem);
1541 QAccessible::Role fileRoles[5] = {
1542 QAccessible::MenuItem,
1543 QAccessible::MenuItem,
1544 QAccessible::MenuItem,
1545 QAccessible::Separator,
1546 QAccessible::MenuItem
1548 for (int child = 0; child < 5; ++child) {
1549 entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2);
1552 QCOMPARE(iface2->role(), fileRoles[child]);
1557 // traverse menu items with navigate(Down, ...)
1558 iface = interface->child(0);
1560 QCOMPARE(iface->role(), QAccessible::MenuItem);
1562 for (int child = 0; child < 4; ++child) {
1563 entry = iface->navigate(QAccessible::Down, 1, &iface2);
1568 QCOMPARE(iface->role(), fileRoles[child + 1]);
1572 // traverse menu items with navigate(Up, ...)
1573 iface = interface->child(interface->childCount() - 1);
1575 QCOMPARE(iface->role(), QAccessible::MenuItem);
1577 for (int child = 3; child >= 0; --child) {
1578 entry = iface->navigate(QAccessible::Up, 1, &iface2);
1583 QCOMPARE(iface->role(), fileRoles[child]);
1588 iface = interface->child(0);
1590 QCOMPARE(iface->role(), QAccessible::MenuItem);
1593 iface2 = iface->child(0);
1598 QCOMPARE(iface->role(), QAccessible::PopupMenu);
1600 // "Text file" menu item
1601 iface2 = iface->child(0);
1605 QCOMPARE(iface->role(), QAccessible::MenuItem);
1609 // move mouse pointer away, since that might influence the
1611 QTest::mouseMove(&mw, QPoint(-1, -1));
1614 QTest::qWait(menuFadeDelay);
1616 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1617 iFileNew->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1619 QVERIFY(file->isVisible());
1620 QVERIFY(fileNew->isVisible());
1621 QVERIFY(!edit->isVisible());
1622 QVERIFY(!help->isVisible());
1624 QTestAccessibility::clearEvents();
1631 delete iFileSeparator;
1634 // Do not crash if the menu don't have a parent
1635 QMenu *menu = new QMenu;
1636 menu->addAction(QLatin1String("one"));
1637 menu->addAction(QLatin1String("two"));
1638 menu->addAction(QLatin1String("three"));
1639 iface = QAccessible::queryAccessibleInterface(menu);
1640 iface2 = iface->parent();
1642 QCOMPARE(iface2->role(), QAccessible::Application);
1650 QTestAccessibility::clearEvents();
1653 void tst_QAccessibility::spinBoxTest()
1655 QSpinBox * const spinBox = new QSpinBox();
1656 spinBox->setValue(3);
1659 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox);
1661 QCOMPARE(interface->role(), QAccessible::SpinBox);
1663 const QRect widgetRect = spinBox->geometry();
1664 const QRect accessibleRect = interface->rect();
1665 QCOMPARE(accessibleRect, widgetRect);
1666 QCOMPARE(interface->text(QAccessible::Value), QLatin1String("3"));
1668 // one child, the line edit
1669 const int numChildren = interface->childCount();
1670 QCOMPARE(numChildren, 1);
1671 QAccessibleInterface *lineEdit = interface->child(0);
1673 QCOMPARE(lineEdit->role(), QAccessible::EditableText);
1674 QCOMPARE(lineEdit->text(QAccessible::Value), QLatin1String("3"));
1677 QVERIFY(interface->valueInterface());
1678 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3);
1679 interface->valueInterface()->setCurrentValue(23);
1680 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23);
1681 QCOMPARE(spinBox->value(), 23);
1683 spinBox->setFocus();
1684 QTestAccessibility::clearEvents();
1685 QTest::keyPress(spinBox, Qt::Key_Up);
1687 EventList events = QTestAccessibility::events();
1688 QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
1689 QVERIFY(events.contains(expectedEvent));
1691 QTestAccessibility::clearEvents();
1694 void tst_QAccessibility::doubleSpinBoxTest()
1696 QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox;
1697 doubleSpinBox->show();
1699 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
1702 const QRect widgetRect = doubleSpinBox->geometry();
1703 const QRect accessibleRect = interface->rect();
1704 QCOMPARE(accessibleRect, widgetRect);
1706 // Test that we get valid rects for all the spinbox child interfaces.
1707 const int numChildren = interface->childCount();
1708 for (int i = 0; i < numChildren; ++i) {
1709 QAccessibleInterface *childIface = interface->child(i);
1710 const QRect childRect = childIface->rect();
1711 QVERIFY(childRect.isValid());
1715 delete doubleSpinBox;
1716 QTestAccessibility::clearEvents();
1719 void tst_QAccessibility::textEditTest()
1725 QString text = "hello world\nhow are you today?\n";
1729 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
1730 QCOMPARE(iface->text(QAccessible::Value), text);
1731 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1732 QCOMPARE(startOffset, 6);
1733 QCOMPARE(endOffset, 11);
1734 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1735 QCOMPARE(startOffset, 12);
1736 QCOMPARE(endOffset, 30);
1737 QCOMPARE(iface->textInterface()->characterCount(), 31);
1738 QFontMetrics fm(edit.font());
1739 QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
1740 QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
1741 QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
1743 QTestAccessibility::clearEvents();
1746 void tst_QAccessibility::textBrowserTest()
1749 QTextBrowser textBrowser;
1750 QString text = QLatin1String("Hello world\nhow are you today?\n");
1751 textBrowser.setText(text);
1754 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
1756 QCOMPARE(iface->role(), QAccessible::StaticText);
1757 QCOMPARE(iface->text(QAccessible::Value), text);
1760 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1761 QCOMPARE(startOffset, 6);
1762 QCOMPARE(endOffset, 11);
1763 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1764 QCOMPARE(startOffset, 12);
1765 QCOMPARE(endOffset, 30);
1766 QCOMPARE(iface->textInterface()->characterCount(), 31);
1768 QTestAccessibility::clearEvents();
1771 void tst_QAccessibility::mdiAreaTest()
1775 mdiArea.resize(400,300);
1777 const int subWindowCount = 3;
1778 for (int i = 0; i < subWindowCount; ++i)
1779 mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show();
1781 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1782 QCOMPARE(subWindows.count(), subWindowCount);
1784 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea);
1786 QCOMPARE(interface->childCount(), subWindowCount);
1788 // Right, right, right, ...
1789 for (int i = 0; i < subWindowCount; ++i) {
1790 QAccessibleInterface *destination = 0;
1791 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
1792 if (i == subWindowCount - 1) {
1793 QVERIFY(!destination);
1794 QCOMPARE(index, -1);
1796 QVERIFY(destination);
1798 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
1803 // Left, left, left, ...
1804 for (int i = subWindowCount; i > 0; --i) {
1805 QAccessibleInterface *destination = 0;
1806 int index = interface->navigate(QAccessible::Left, i, &destination);
1808 QVERIFY(!destination);
1809 QCOMPARE(index, -1);
1811 QVERIFY(destination);
1813 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
1817 // ### Add test for Up and Down.
1820 QTestAccessibility::clearEvents();
1823 void tst_QAccessibility::mdiSubWindowTest()
1828 qApp->setActiveWindow(&mdiArea);
1829 #if defined(Q_OS_UNIX)
1830 QCoreApplication::processEvents();
1834 bool isSubWindowsPlacedNextToEachOther = false;
1835 const int subWindowCount = 5;
1836 for (int i = 0; i < subWindowCount; ++i) {
1837 QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
1839 // Parts of this test requires that the sub windows are placed next
1840 // to each other. In order to achieve that QMdiArea must have
1841 // a width which is larger than subWindow->width() * subWindowCount.
1843 int minimumWidth = window->width() * subWindowCount + 20;
1844 mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0)));
1845 #if defined(Q_OS_UNIX)
1846 QCoreApplication::processEvents();
1849 if (mdiArea.width() >= minimumWidth)
1850 isSubWindowsPlacedNextToEachOther = true;
1854 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1855 QCOMPARE(subWindows.count(), subWindowCount);
1857 QMdiSubWindow *testWindow = subWindows.at(3);
1858 QVERIFY(testWindow);
1859 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow);
1863 QCOMPARE(interface->childCount(), 1);
1866 QCOMPARE(interface->text(QAccessible::Name), QString());
1867 testWindow->setWindowTitle(QLatin1String("ReplaceMe"));
1868 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("ReplaceMe"));
1869 interface->setText(QAccessible::Name, QLatin1String("TitleSetOnWindow"));
1870 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("TitleSetOnWindow"));
1872 mdiArea.setActiveSubWindow(testWindow);
1875 QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused
1876 | QAccessible::Movable | QAccessible::Sizeable;
1877 QCOMPARE(interface->state(), state);
1878 const QRect originalGeometry = testWindow->geometry();
1879 testWindow->showMaximized();
1880 state &= (uint)~QAccessible::Sizeable;
1881 state &= (uint)~QAccessible::Movable;
1882 QCOMPARE(interface->state(), state);
1883 testWindow->showNormal();
1884 testWindow->move(-10, 0);
1885 QVERIFY(interface->state() & QAccessible::Offscreen);
1886 testWindow->setVisible(false);
1887 QVERIFY(interface->state() & QAccessible::Invisible);
1888 testWindow->setVisible(true);
1889 testWindow->setEnabled(false);
1890 QVERIFY(interface->state() & QAccessible::Unavailable);
1891 testWindow->setEnabled(true);
1892 qApp->setActiveWindow(&mdiArea);
1893 mdiArea.setActiveSubWindow(testWindow);
1894 testWindow->setFocus();
1895 QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
1896 QVERIFY(interface->state() & QAccessible::Focused);
1897 testWindow->setGeometry(originalGeometry);
1899 if (isSubWindowsPlacedNextToEachOther) {
1900 // This part of the test can only be run if the sub windows are
1901 // placed next to each other.
1902 QAccessibleInterface *destination = interface->child(0);
1903 QVERIFY(destination);
1904 QCOMPARE(destination->object(), (QObject*)testWindow->widget());
1906 QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0);
1907 QVERIFY(destination);
1908 QCOMPARE(destination->object(), (QObject*)subWindows.at(2));
1910 QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0);
1911 QVERIFY(destination);
1912 QCOMPARE(destination->object(), (QObject*)subWindows.at(4));
1917 const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0));
1918 QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size()));
1920 QCOMPARE(interface->rect(), QRect());
1921 QCOMPARE(childRect(interface), QRect());
1922 testWindow->showMinimized();
1923 QCOMPARE(childRect(interface), QRect());
1924 testWindow->showNormal();
1925 testWindow->widget()->hide();
1926 QCOMPARE(childRect(interface), QRect());
1927 testWindow->widget()->show();
1928 const QRect widgetGeometry = testWindow->contentsRect();
1929 const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
1930 globalPos.y() + widgetGeometry.y());
1931 QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
1934 QCOMPARE(interface->childAt(-10, 0), -1);
1935 QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0);
1936 QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1);
1937 testWindow->widget()->hide();
1938 QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0);
1941 QTestAccessibility::clearEvents();
1944 void tst_QAccessibility::lineEditTest()
1946 QLineEdit *le = new QLineEdit;
1947 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
1951 QApplication::processEvents();
1952 QCOMPARE(iface->childCount(), 0);
1953 QVERIFY(iface->state() & QAccessible::Sizeable);
1954 QVERIFY(iface->state() & QAccessible::Movable);
1955 QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1956 QVERIFY(iface->state() & QAccessible::Selectable);
1957 QVERIFY(iface->state() & QAccessible::HasPopup);
1958 QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1960 QString secret(QLatin1String("secret"));
1961 le->setText(secret);
1962 le->setEchoMode(QLineEdit::Normal);
1963 QVERIFY(!(iface->state() & QAccessible::Protected));
1964 QCOMPARE(iface->text(QAccessible::Value), secret);
1965 le->setEchoMode(QLineEdit::NoEcho);
1966 QVERIFY(iface->state() & QAccessible::Protected);
1967 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1968 le->setEchoMode(QLineEdit::Password);
1969 QVERIFY(iface->state() & QAccessible::Protected);
1970 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1971 le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
1972 QVERIFY(iface->state() & QAccessible::Protected);
1973 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1974 le->setEchoMode(QLineEdit::Normal);
1975 QVERIFY(!(iface->state() & QAccessible::Protected));
1976 QCOMPARE(iface->text(QAccessible::Value), secret);
1978 QWidget *toplevel = new QWidget;
1979 le->setParent(toplevel);
1981 QApplication::processEvents();
1982 QVERIFY(!(iface->state() & QAccessible::Sizeable));
1983 QVERIFY(!(iface->state() & QAccessible::Movable));
1984 QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1985 QVERIFY(iface->state() & QAccessible::Selectable);
1986 QVERIFY(iface->state() & QAccessible::HasPopup);
1987 QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1989 QLineEdit *le2 = new QLineEdit(toplevel);
1992 le2->activateWindow();
1994 le->setFocus(Qt::TabFocusReason);
1995 QTestAccessibility::clearEvents();
1996 le2->setFocus(Qt::TabFocusReason);
1997 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
1999 le->setText(QLatin1String("500"));
2000 le->setValidator(new QIntValidator());
2001 iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
2002 QCOMPARE(le->text(), QLatin1String("500"));
2007 QTestAccessibility::clearEvents();
2010 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";
2011 QLineEdit *le3 = new QLineEdit(cite, toplevel);
2012 iface = QAccessible::queryAccessibleInterface(le3);
2013 QAccessibleTextInterface* textIface = iface->textInterface();
2015 le3->setCursorPosition(3);
2016 QCOMPARE(textIface->cursorPosition(), 3);
2017 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
2018 QCOMPARE(textIface->selectionCount(), 0);
2019 QTestAccessibility::clearEvents();
2022 QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
2023 QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
2026 QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString());
2027 QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" "));
2031 QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a"));
2034 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w"));
2035 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y"));
2037 QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2041 QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2042 QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2043 QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2044 QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
2045 QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
2047 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2048 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2049 QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2053 QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2054 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. "));
2056 QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite);
2058 QCOMPARE(end, cite.length());
2059 QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
2060 QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
2064 QTestAccessibility::clearEvents();
2067 void tst_QAccessibility::workspaceTest()
2070 QWorkspace workspace;
2071 workspace.resize(400,300);
2073 const int subWindowCount = 3;
2074 for (int i = 0; i < subWindowCount; ++i) {
2075 QWidget *window = workspace.addWindow(new QWidget);
2077 window->move(window->x() + 1, window->y());
2079 window->resize(70, window->height());
2082 QWidgetList subWindows = workspace.windowList();
2083 QCOMPARE(subWindows.count(), subWindowCount);
2085 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
2087 QCOMPARE(interface->childCount(), subWindowCount);
2089 // Right, right, right, ...
2090 for (int i = 0; i < subWindowCount; ++i) {
2091 QAccessibleInterface *destination = 0;
2092 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
2093 if (i == subWindowCount - 1) {
2094 QVERIFY(!destination);
2095 QCOMPARE(index, -1);
2097 QVERIFY(destination);
2099 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
2104 // Left, left, left, ...
2105 for (int i = subWindowCount; i > 0; --i) {
2106 QAccessibleInterface *destination = 0;
2107 int index = interface->navigate(QAccessible::Left, i, &destination);
2109 QVERIFY(!destination);
2110 QCOMPARE(index, -1);
2112 QVERIFY(destination);
2114 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
2118 // ### Add test for Up and Down.
2121 QTestAccessibility::clearEvents();
2124 void tst_QAccessibility::dialogButtonBoxTest()
2127 QDialogButtonBox box(QDialogButtonBox::Reset |
2128 QDialogButtonBox::Help |
2129 QDialogButtonBox::Ok, Qt::Horizontal);
2132 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2135 #if defined(Q_OS_UNIX)
2136 QCoreApplication::processEvents();
2140 QApplication::processEvents();
2141 QCOMPARE(iface->childCount(), 3);
2142 QCOMPARE(iface->role(), QAccessible::Grouping);
2143 QStringList actualOrder;
2144 QAccessibleInterface *child;
2145 QAccessibleInterface *leftmost;
2146 child = iface->child(0);
2147 QCOMPARE(child->role(), QAccessible::PushButton);
2149 // first find the leftmost button
2150 while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) {
2156 // then traverse from left to right to find the correct order of the buttons
2158 while (right != -1) {
2159 actualOrder << leftmost->text(QAccessible::Name);
2160 right = leftmost->navigate(QAccessible::Right, 1, &child);
2165 QStringList expectedOrder;
2166 QDialogButtonBox::ButtonLayout btnlout =
2167 QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout));
2169 case QDialogButtonBox::WinLayout:
2170 expectedOrder << QDialogButtonBox::tr("Reset")
2171 << QDialogButtonBox::tr("OK")
2172 << QDialogButtonBox::tr("Help");
2174 case QDialogButtonBox::GnomeLayout:
2175 case QDialogButtonBox::KdeLayout:
2176 case QDialogButtonBox::MacLayout:
2177 expectedOrder << QDialogButtonBox::tr("Help")
2178 << QDialogButtonBox::tr("Reset")
2179 << QDialogButtonBox::tr("OK");
2182 QCOMPARE(actualOrder, expectedOrder);
2184 QApplication::processEvents();
2185 QTestAccessibility::clearEvents();
2189 QDialogButtonBox box(QDialogButtonBox::Reset |
2190 QDialogButtonBox::Help |
2191 QDialogButtonBox::Ok, Qt::Horizontal);
2194 // Test up and down navigation
2195 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2197 box.setOrientation(Qt::Vertical);
2199 #if defined(Q_OS_UNIX)
2200 QCoreApplication::processEvents();
2204 QApplication::processEvents();
2205 QAccessibleInterface *child;
2206 QStringList actualOrder;
2207 child = iface->child(0);
2208 // first find the topmost button
2209 QAccessibleInterface *other;
2210 while (child->navigate(QAccessible::Up, 1, &other) != -1) {
2216 // then traverse from top to bottom to find the correct order of the buttons
2217 actualOrder.clear();
2219 while (right != -1) {
2220 actualOrder << other->text(QAccessible::Name);
2221 right = other->navigate(QAccessible::Down, 1, &child);
2226 QStringList expectedOrder;
2227 expectedOrder << QDialogButtonBox::tr("OK")
2228 << QDialogButtonBox::tr("Reset")
2229 << QDialogButtonBox::tr("Help");
2231 QCOMPARE(actualOrder, expectedOrder);
2233 QApplication::processEvents();
2236 QTestAccessibility::clearEvents();
2239 void tst_QAccessibility::dialTest()
2243 dial.setMinimum(23);
2244 dial.setMaximum(121);
2246 QCOMPARE(dial.value(), 42);
2249 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial);
2251 QCOMPARE(interface->childCount(), 0);
2253 QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value()));
2254 QCOMPARE(interface->rect(), dial.geometry());
2256 QAccessibleValueInterface *valueIface = interface->valueInterface();
2257 QVERIFY(valueIface != 0);
2258 QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum());
2259 QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum());
2260 QCOMPARE(valueIface->currentValue().toInt(), 42);
2262 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2264 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2266 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2267 valueIface->setCurrentValue(77);
2268 QCOMPARE(77, dial.value());
2270 QTestAccessibility::clearEvents();
2273 void tst_QAccessibility::rubberBandTest()
2275 QRubberBand rubberBand(QRubberBand::Rectangle);
2276 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand);
2278 QCOMPARE(interface->role(), QAccessible::Border);
2280 QTestAccessibility::clearEvents();
2283 void tst_QAccessibility::abstractScrollAreaTest()
2286 QAbstractScrollArea abstractScrollArea;
2288 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
2290 QVERIFY(!interface->rect().isValid());
2291 QCOMPARE(interface->childAt(200, 200), -1);
2293 abstractScrollArea.resize(400, 400);
2294 abstractScrollArea.show();
2295 #if defined(Q_OS_UNIX)
2296 QCoreApplication::processEvents();
2299 const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)),
2300 abstractScrollArea.size());
2303 QCOMPARE(interface->childCount(), 1);
2304 QWidget *viewport = abstractScrollArea.viewport();
2306 QVERIFY(verifyChild(viewport, interface, 1, globalGeometry));
2308 // Horizontal scrollBar.
2309 abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2310 QCOMPARE(interface->childCount(), 2);
2311 QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar();
2312 QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget();
2313 QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry));
2315 // Horizontal scrollBar widgets.
2316 QLabel *secondLeftLabel = new QLabel(QLatin1String("L2"));
2317 abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft);
2318 QCOMPARE(interface->childCount(), 2);
2320 QLabel *firstLeftLabel = new QLabel(QLatin1String("L1"));
2321 abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft);
2322 QCOMPARE(interface->childCount(), 2);
2324 QLabel *secondRightLabel = new QLabel(QLatin1String("R2"));
2325 abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight);
2326 QCOMPARE(interface->childCount(), 2);
2328 QLabel *firstRightLabel = new QLabel(QLatin1String("R1"));
2329 abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight);
2330 QCOMPARE(interface->childCount(), 2);
2332 // Vertical scrollBar.
2333 abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2334 QCOMPARE(interface->childCount(), 3);
2335 QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar();
2336 QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget();
2337 QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry));
2339 // Vertical scrollBar widgets.
2340 QLabel *secondTopLabel = new QLabel(QLatin1String("T2"));
2341 abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop);
2342 QCOMPARE(interface->childCount(), 3);
2344 QLabel *firstTopLabel = new QLabel(QLatin1String("T1"));
2345 abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop);
2346 QCOMPARE(interface->childCount(), 3);
2348 QLabel *secondBottomLabel = new QLabel(QLatin1String("B2"));
2349 abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom);
2350 QCOMPARE(interface->childCount(), 3);
2352 QLabel *firstBottomLabel = new QLabel(QLatin1String("B1"));
2353 abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom);
2354 QCOMPARE(interface->childCount(), 3);
2357 abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C")));
2358 QCOMPARE(interface->childCount(), 4);
2359 QWidget *cornerWidget = abstractScrollArea.cornerWidget();
2360 QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry));
2363 QAccessibleInterface *target = 0;
2365 // viewport -> Up -> NOTHING
2366 const int viewportIndex = indexOfChild(interface, viewport);
2367 QVERIFY(viewportIndex != -1);
2368 QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1);
2371 // viewport -> Left -> NOTHING
2372 QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1);
2375 // viewport -> Down -> horizontalScrollBarContainer
2376 const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer);
2377 QVERIFY(horizontalScrollBarContainerIndex != -1);
2378 QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0);
2380 QCOMPARE(target->object(), static_cast<QObject *>(horizontalScrollBarContainer));
2384 // horizontalScrollBarContainer -> Left -> NOTHING
2385 QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1);
2388 // horizontalScrollBarContainer -> Down -> NOTHING
2389 QVERIFY(horizontalScrollBarContainerIndex != -1);
2390 QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1);
2393 // horizontalScrollBarContainer -> Right -> cornerWidget
2394 const int cornerWidgetIndex = indexOfChild(interface, cornerWidget);
2395 QVERIFY(cornerWidgetIndex != -1);
2396 QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0);
2398 QCOMPARE(target->object(), static_cast<QObject *>(cornerWidget));
2402 // cornerWidget -> Down -> NOTHING
2403 QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1);
2406 // cornerWidget -> Right -> NOTHING
2407 QVERIFY(cornerWidgetIndex != -1);
2408 QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1);
2411 // cornerWidget -> Up -> verticalScrollBarContainer
2412 const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer);
2413 QVERIFY(verticalScrollBarContainerIndex != -1);
2414 QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0);
2416 QCOMPARE(target->object(), static_cast<QObject *>(verticalScrollBarContainer));
2420 // verticalScrollBarContainer -> Right -> NOTHING
2421 QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1);
2424 // verticalScrollBarContainer -> Up -> NOTHING
2425 QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1);
2428 // verticalScrollBarContainer -> Left -> viewport
2429 QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0);
2431 QCOMPARE(target->object(), static_cast<QObject *>(viewport));
2435 QCOMPARE(verifyHierarchy(interface), 0);
2440 QTestAccessibility::clearEvents();
2443 void tst_QAccessibility::scrollAreaTest()
2446 QScrollArea scrollArea;
2448 #if defined(Q_OS_UNIX)
2449 QCoreApplication::processEvents();
2452 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea);
2454 QCOMPARE(interface->childCount(), 1); // The viewport.
2457 QTestAccessibility::clearEvents();
2460 void tst_QAccessibility::listTest()
2462 QListWidget *listView = new QListWidget;
2463 listView->addItem("Oslo");
2464 listView->addItem("Berlin");
2465 listView->addItem("Brisbane");
2466 listView->resize(400,400);
2468 QTest::qWait(1); // Need this for indexOfchild to work.
2469 QCoreApplication::processEvents();
2472 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView);
2473 QCOMPARE(verifyHierarchy(iface), 0);
2475 QCOMPARE((int)iface->role(), (int)QAccessible::List);
2476 QCOMPARE(iface->childCount(), 3);
2478 QAccessibleInterface *child1 = 0;
2479 child1 = iface->child(0);
2481 QCOMPARE(iface->indexOfChild(child1), 1);
2482 QCOMPARE(child1->text(QAccessible::Name), QString("Oslo"));
2483 QCOMPARE(child1->role(), QAccessible::ListItem);
2486 QAccessibleInterface *child2 = 0;
2487 child2 = iface->child(1);
2489 QCOMPARE(iface->indexOfChild(child2), 2);
2490 QCOMPARE(child2->text(QAccessible::Name), QString("Berlin"));
2493 QAccessibleInterface *child3 = 0;
2494 child3 = iface->child(2);
2496 QCOMPARE(iface->indexOfChild(child3), 3);
2497 QCOMPARE(child3->text(QAccessible::Name), QString("Brisbane"));
2499 QTestAccessibility::clearEvents();
2502 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
2503 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
2504 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
2505 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
2506 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
2507 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
2509 listView->addItem("Munich");
2510 QCOMPARE(iface->childCount(), 4);
2513 QAccessibleTableInterface *table2 = iface->tableInterface();
2515 QCOMPARE(table2->columnCount(), 1);
2516 QCOMPARE(table2->rowCount(), 4);
2517 QAccessibleInterface *cell1;
2518 QVERIFY(cell1 = table2->cellAt(0,0));
2519 QCOMPARE(cell1->text(QAccessible::Name), QString("Oslo"));
2520 QAccessibleInterface *cell4;
2521 QVERIFY(cell4 = table2->cellAt(3,0));
2522 QCOMPARE(cell4->text(QAccessible::Name), QString("Munich"));
2523 QCOMPARE(cell4->role(), QAccessible::ListItem);
2525 QAccessibleTableCellInterface *cellInterface = cell4->tableCellInterface();
2526 QVERIFY(cellInterface);
2527 QCOMPARE(cellInterface->rowIndex(), 3);
2528 QCOMPARE(cellInterface->columnIndex(), 0);
2529 QVERIFY(!(cell4->state() & QAccessible::Expandable));
2535 QTestAccessibility::clearEvents();
2538 void tst_QAccessibility::treeTest()
2540 QTreeWidget *treeView = new QTreeWidget;
2541 treeView->setColumnCount(2);
2542 QTreeWidgetItem *header = new QTreeWidgetItem;
2543 header->setText(0, "Artist");
2544 header->setText(1, "Work");
2545 treeView->setHeaderItem(header);
2547 QTreeWidgetItem *root1 = new QTreeWidgetItem;
2548 root1->setText(0, "Spain");
2549 treeView->addTopLevelItem(root1);
2551 QTreeWidgetItem *item1 = new QTreeWidgetItem;
2552 item1->setText(0, "Picasso");
2553 item1->setText(1, "Guernica");
2554 root1->addChild(item1);
2556 QTreeWidgetItem *item2 = new QTreeWidgetItem;
2557 item2->setText(0, "Tapies");
2558 item2->setText(1, "Ambrosia");
2559 root1->addChild(item2);
2561 QTreeWidgetItem *root2 = new QTreeWidgetItem;
2562 root2->setText(0, "Austria");
2563 treeView->addTopLevelItem(root2);
2565 QTreeWidgetItem *item3 = new QTreeWidgetItem;
2566 item3->setText(0, "Klimt");
2567 item3->setText(1, "The Kiss");
2568 root2->addChild(item3);
2570 treeView->resize(400,400);
2573 QCoreApplication::processEvents();
2576 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
2577 QCOMPARE(verifyHierarchy(iface), 0);
2579 QCOMPARE((int)iface->role(), (int)QAccessible::Tree);
2580 // header and 2 rows (the others are not expanded, thus not visible)
2581 QCOMPARE(iface->childCount(), 6);
2583 QAccessibleInterface *header1 = 0;
2584 header1 = iface->child(0);
2586 QCOMPARE(iface->indexOfChild(header1), 1);
2587 QCOMPARE(header1->text(QAccessible::Name), QString("Artist"));
2588 QCOMPARE(header1->role(), QAccessible::ColumnHeader);
2591 QAccessibleInterface *child1 = 0;
2592 child1 = iface->child(2);
2594 QCOMPARE(iface->indexOfChild(child1), 3);
2595 QCOMPARE(child1->text(QAccessible::Name), QString("Spain"));
2596 QCOMPARE(child1->role(), QAccessible::TreeItem);
2597 QVERIFY(!(child1->state() & QAccessible::Expanded));
2600 QAccessibleInterface *child2 = 0;
2601 child2 = iface->child(4);
2603 QCOMPARE(iface->indexOfChild(child2), 5);
2604 QCOMPARE(child2->text(QAccessible::Name), QString("Austria"));
2607 QTestAccessibility::clearEvents();
2610 QAccessibleTableInterface *table2 = iface->tableInterface();
2612 QCOMPARE(table2->columnCount(), 2);
2613 QCOMPARE(table2->rowCount(), 2);
2614 QAccessibleInterface *cell1;
2615 QVERIFY(cell1 = table2->cellAt(0,0));
2616 QCOMPARE(cell1->text(QAccessible::Name), QString("Spain"));
2617 QAccessibleInterface *cell2;
2618 QVERIFY(cell2 = table2->cellAt(1,0));
2619 QCOMPARE(cell2->text(QAccessible::Name), QString("Austria"));
2620 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2621 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1);
2622 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2623 QVERIFY(cell2->state() & QAccessible::Expandable);
2624 QCOMPARE(iface->indexOfChild(cell2), 5);
2625 QVERIFY(!(cell2->state() & QAccessible::Expanded));
2626 QCOMPARE(table2->columnDescription(1), QString("Work"));
2630 treeView->expandAll();
2632 // Need this for indexOfchild to work.
2633 QCoreApplication::processEvents();
2636 QCOMPARE(table2->columnCount(), 2);
2637 QCOMPARE(table2->rowCount(), 5);
2638 cell1 = table2->cellAt(1,0);
2639 QCOMPARE(cell1->text(QAccessible::Name), QString("Picasso"));
2640 QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
2642 cell2 = table2->cellAt(4,0);
2643 QCOMPARE(cell2->text(QAccessible::Name), QString("Klimt"));
2644 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2645 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4);
2646 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2647 QVERIFY(!(cell2->state() & QAccessible::Expandable));
2648 QCOMPARE(iface->indexOfChild(cell2), 11);
2650 QCOMPARE(table2->columnDescription(0), QString("Artist"));
2651 QCOMPARE(table2->columnDescription(1), QString("Work"));
2654 QTestAccessibility::clearEvents();
2657 void tst_QAccessibility::tableTest()
2659 QTableWidget *tableView = new QTableWidget(3, 3);
2660 tableView->setColumnCount(3);
2661 QStringList hHeader;
2662 hHeader << "h1" << "h2" << "h3";
2663 tableView->setHorizontalHeaderLabels(hHeader);
2665 QStringList vHeader;
2666 vHeader << "v1" << "v2" << "v3";
2667 tableView->setVerticalHeaderLabels(vHeader);
2669 for (int i = 0; i<9; ++i) {
2670 QTableWidgetItem *item = new QTableWidgetItem;
2671 item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
2672 tableView->setItem(i/3, i%3, item);
2675 tableView->resize(600,600);
2677 QTest::qWait(1); // Need this for indexOfchild to work.
2678 QCoreApplication::processEvents();
2681 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
2682 QCOMPARE(verifyHierarchy(iface), 0);
2684 QCOMPARE((int)iface->role(), (int)QAccessible::Table);
2685 // header and 2 rows (the others are not expanded, thus not visible)
2686 QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
2688 QAccessibleInterface *cornerButton = iface->child(0);
2689 QVERIFY(cornerButton);
2690 QCOMPARE(iface->indexOfChild(cornerButton), 1);
2691 QCOMPARE(cornerButton->role(), QAccessible::Pane);
2692 delete cornerButton;
2694 QAccessibleInterface *child1 = iface->child(2);
2696 QCOMPARE(iface->indexOfChild(child1), 3);
2697 QCOMPARE(child1->text(QAccessible::Name), QString("h2"));
2698 QCOMPARE(child1->role(), QAccessible::ColumnHeader);
2699 QVERIFY(!(child1->state() & QAccessible::Expanded));
2702 QAccessibleInterface *child2 = iface->child(10);
2704 QCOMPARE(iface->indexOfChild(child2), 11);
2705 QCOMPARE(child2->text(QAccessible::Name), QString("1.1"));
2706 QAccessibleTableCellInterface *cell2Iface = child2->tableCellInterface();
2707 QCOMPARE(cell2Iface->rowIndex(), 1);
2708 QCOMPARE(cell2Iface->columnIndex(), 1);
2711 QAccessibleInterface *child3 = iface->child(11);
2712 QCOMPARE(iface->indexOfChild(child3), 12);
2713 QCOMPARE(child3->text(QAccessible::Name), QString("1.2"));
2716 QTestAccessibility::clearEvents();
2719 QAccessibleTableInterface *table2 = iface->tableInterface();
2721 QCOMPARE(table2->columnCount(), 3);
2722 QCOMPARE(table2->rowCount(), 3);
2723 QAccessibleInterface *cell1;
2724 QVERIFY(cell1 = table2->cellAt(0,0));
2725 QCOMPARE(cell1->text(QAccessible::Name), QString("0.0"));
2726 QCOMPARE(iface->indexOfChild(cell1), 6);
2728 QAccessibleInterface *cell2;
2729 QVERIFY(cell2 = table2->cellAt(0,1));
2730 QCOMPARE(cell2->text(QAccessible::Name), QString("0.1"));
2731 QCOMPARE(cell2->role(), QAccessible::Cell);
2732 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 0);
2733 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 1);
2734 QCOMPARE(iface->indexOfChild(cell2), 7);
2737 QAccessibleInterface *cell3;
2738 QVERIFY(cell3 = table2->cellAt(1,2));
2739 QCOMPARE(cell3->text(QAccessible::Name), QString("1.2"));
2740 QCOMPARE(cell3->role(), QAccessible::Cell);
2741 QCOMPARE(cell3->tableCellInterface()->rowIndex(), 1);
2742 QCOMPARE(cell3->tableCellInterface()->columnIndex(), 2);
2743 QCOMPARE(iface->indexOfChild(cell3), 12);
2746 QCOMPARE(table2->columnDescription(0), QString("h1"));
2747 QCOMPARE(table2->columnDescription(1), QString("h2"));
2748 QCOMPARE(table2->columnDescription(2), QString("h3"));
2749 QCOMPARE(table2->rowDescription(0), QString("v1"));
2750 QCOMPARE(table2->rowDescription(1), QString("v2"));
2751 QCOMPARE(table2->rowDescription(2), QString("v3"));
2757 QTestAccessibility::clearEvents();
2760 void tst_QAccessibility::calendarWidgetTest()
2762 #ifndef QT_NO_CALENDARWIDGET
2764 QCalendarWidget calendarWidget;
2766 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget);
2768 QCOMPARE(interface->role(), QAccessible::Table);
2769 QVERIFY(!interface->rect().isValid());
2770 QCOMPARE(interface->childAt(200, 200), -1);
2772 calendarWidget.resize(400, 300);
2773 calendarWidget.show();
2774 #if defined(Q_OS_UNIX)
2775 QCoreApplication::processEvents();
2779 // 1 = navigationBar, 2 = view.
2780 QCOMPARE(interface->childCount(), 2);
2782 const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)),
2783 calendarWidget.size());
2784 QCOMPARE(interface->rect(), globalGeometry);
2786 QWidget *navigationBar = 0;
2787 foreach (QObject *child, calendarWidget.children()) {
2788 if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) {
2789 navigationBar = static_cast<QWidget *>(child);
2793 QVERIFY(navigationBar);
2794 QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry));
2796 QAbstractItemView *calendarView = 0;
2797 foreach (QObject *child, calendarWidget.children()) {
2798 if (child->objectName() == QLatin1String("qt_calendar_calendarview")) {
2799 calendarView = static_cast<QAbstractItemView *>(child);
2803 QVERIFY(calendarView);
2804 QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry));
2806 // Hide navigation bar.
2807 calendarWidget.setNavigationBarVisible(false);
2808 QCOMPARE(interface->childCount(), 1);
2809 QVERIFY(!navigationBar->isVisible());
2811 QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry));
2813 // Show navigation bar.
2814 calendarWidget.setNavigationBarVisible(true);
2815 QCOMPARE(interface->childCount(), 2);
2816 QVERIFY(navigationBar->isVisible());
2818 // Navigate to the navigation bar via Child.
2819 QAccessibleInterface *navigationBarInterface = interface->child(0);
2820 QVERIFY(navigationBarInterface);
2821 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2822 delete navigationBarInterface;
2823 navigationBarInterface = 0;
2825 // Navigate to the view via Child.
2826 QAccessibleInterface *calendarViewInterface = interface->child(1);
2827 QVERIFY(calendarViewInterface);
2828 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2829 delete calendarViewInterface;
2830 calendarViewInterface = 0;
2832 QVERIFY(!interface->child(-1));
2834 // Navigate from navigation bar -> view (Down).
2835 QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0);
2836 QVERIFY(calendarViewInterface);
2837 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2838 delete calendarViewInterface;
2839 calendarViewInterface = 0;
2841 // Navigate from view -> navigation bar (Up).
2842 QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0);
2843 QVERIFY(navigationBarInterface);
2844 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2845 delete navigationBarInterface;
2846 navigationBarInterface = 0;
2849 QTestAccessibility::clearEvents();
2850 #endif // QT_NO_CALENDARWIDGET
2853 void tst_QAccessibility::dockWidgetTest()
2855 #ifndef QT_NO_DOCKWIDGET
2856 // Set up a proper main window with two dock widgets
2857 QMainWindow *mw = new QMainWindow();
2858 QFrame *central = new QFrame(mw);
2859 mw->setCentralWidget(central);
2860 QMenuBar *mb = new QMenuBar(mw);
2861 mb->addAction(tr("&File"));
2864 QDockWidget *dock1 = new QDockWidget(mw);
2865 mw->addDockWidget(Qt::LeftDockWidgetArea, dock1);
2866 QPushButton *pb1 = new QPushButton(tr("Push me"), dock1);
2867 dock1->setWidget(pb1);
2869 QDockWidget *dock2 = new QDockWidget(mw);
2870 mw->addDockWidget(Qt::BottomDockWidgetArea, dock2);
2871 QPushButton *pb2 = new QPushButton(tr("Push me"), dock2);
2872 dock2->setWidget(pb2);
2874 mw->resize(600,400);
2876 #if defined(Q_OS_UNIX)
2877 QCoreApplication::processEvents();
2881 QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw);
2882 // 4 children: menu bar, dock1, dock2, and central widget
2883 QCOMPARE(accMainWindow->childCount(), 4);
2884 QAccessibleInterface *accDock1 = 0;
2885 for (int i = 0; i < 4; ++i) {
2886 accDock1 = accMainWindow->child(i);
2887 if (accMainWindow->role() == QAccessible::Window) {
2888 if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) {
2896 QCOMPARE(accDock1->role(), QAccessible::Window);
2898 QAccessibleInterface *dock1TitleBar = accDock1->child(0);
2899 QCOMPARE(dock1TitleBar->role(), QAccessible::TitleBar);
2900 QVERIFY(accDock1->rect().contains(dock1TitleBar->rect()));
2901 delete dock1TitleBar;
2903 QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
2904 globalPos.rx()+=5; //### query style
2906 int entry = accDock1->childAt(globalPos.x(), globalPos.y()); //###
2908 QAccessibleInterface *accTitleBar = accDock1->child(entry - 1);
2910 QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
2911 QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);
2912 QAccessibleInterface *acc;
2913 acc = accTitleBar->parent();
2915 QCOMPARE(acc->role(), QAccessible::Window);
2925 QTestAccessibility::clearEvents();
2926 #endif // QT_NO_DOCKWIDGET
2929 void tst_QAccessibility::comboBoxTest()
2931 #if defined(Q_OS_WINCE)
2932 if (!IsValidCEPlatform())
2933 QSKIP("Test skipped on Windows Mobile test hardware");
2935 { // not editable combobox
2937 combo.addItems(QStringList() << "one" << "two" << "three");
2939 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
2940 QCOMPARE(verifyHierarchy(iface), 0);
2942 QCOMPARE(iface->role(), QAccessible::ComboBox);
2943 QCOMPARE(iface->childCount(), 1);
2946 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one"));
2948 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one"));
2949 combo.setCurrentIndex(2);
2951 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three"));
2953 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three"));
2955 QAccessibleInterface *listIface = iface->child(0);
2956 QCOMPARE(listIface->role(), QAccessible::List);
2957 QCOMPARE(listIface->childCount(), 3);
2959 QVERIFY(!combo.view()->isVisible());
2960 QVERIFY(iface->actionInterface());
2961 QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
2962 iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
2963 QVERIFY(combo.view()->isVisible());
2968 { // editable combobox
2969 QComboBox editableCombo;
2970 editableCombo.show();
2971 editableCombo.setEditable(true);
2972 editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
2974 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo);
2975 QCOMPARE(verifyHierarchy(iface), 0);
2977 QCOMPARE(iface->role(), QAccessible::ComboBox);
2978 QCOMPARE(iface->childCount(), 2);
2980 QAccessibleInterface *listIface = iface->child(0);
2981 QCOMPARE(listIface->role(), QAccessible::List);
2982 QAccessibleInterface *editIface = iface->child(1);
2983 QCOMPARE(editIface->role(), QAccessible::EditableText);
2990 QTestAccessibility::clearEvents();
2993 void tst_QAccessibility::labelTest()
2995 QString text = "Hello World";
2996 QLabel *label = new QLabel(text);
2999 #if defined(Q_OS_UNIX)
3000 QCoreApplication::processEvents();
3004 QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label);
3007 QCOMPARE(acc_label->text(QAccessible::Name), text);
3011 QTestAccessibility::clearEvents();
3013 QPixmap testPixmap(50, 50);
3017 imageLabel.setPixmap(testPixmap);
3018 imageLabel.setToolTip("Test Description");
3020 acc_label = QAccessible::queryAccessibleInterface(&imageLabel);
3023 QAccessibleImageInterface *imageInterface = acc_label->imageInterface();
3024 QVERIFY(imageInterface);
3026 QCOMPARE(imageInterface->imageSize(), testPixmap.size());
3027 QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
3028 QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
3032 QTestAccessibility::clearEvents();
3035 void tst_QAccessibility::accelerators()
3037 QWidget *window = new QWidget;
3038 QHBoxLayout *lay = new QHBoxLayout(window);
3039 QLabel *label = new QLabel(tr("&Line edit"), window);
3040 QLineEdit *le = new QLineEdit(window);
3041 lay->addWidget(label);
3043 label->setBuddy(le);
3047 QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
3048 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3049 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3050 label->setText(tr("Q &"));
3051 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3052 label->setText(tr("Q &&"));
3053 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3054 label->setText(tr("Q && A"));
3055 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3056 label->setText(tr("Q &&&A"));
3057 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3058 label->setText(tr("Q &&A"));
3059 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3061 #if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC)
3062 QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'");
3064 label->setText(tr("Q &A&B"));
3065 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3067 #if defined(Q_OS_UNIX)
3068 QCoreApplication::processEvents();
3072 QTestAccessibility::clearEvents();
3075 QTEST_MAIN(tst_QAccessibility)
3076 #include "tst_qaccessibility.moc"