1 /****************************************************************************
3 ** Copyright (C) 2012 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 typedef QSharedPointer<QAccessibleInterface> QAIPtr;
71 static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
72 int index, const QRect &domain)
75 qWarning("tst_QAccessibility::verifyChild: null pointer to child.");
80 qWarning("tst_QAccessibility::verifyChild: null pointer to interface.");
84 // Verify that we get a valid QAccessibleInterface for the child.
85 QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child);
86 if (!childInterface) {
87 qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child.");
91 // QAccessibleInterface::indexOfChild():
92 // Verify that indexOfChild() returns an index equal to the index passed in
93 int indexFromIndexOfChild = interface->indexOfChild(childInterface);
94 if (indexFromIndexOfChild != index) {
95 qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
96 qWarning() << "Expected:" << index;
97 qWarning() << "Actual: " << indexFromIndexOfChild;
101 // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child).
102 QAccessibleInterface *navigatedChildInterface = interface->child(index - 1);
103 if (navigatedChildInterface == 0)
106 const QRect rectFromInterface = navigatedChildInterface->rect();
107 delete navigatedChildInterface;
109 // QAccessibleInterface::childAt():
110 // Calculate global child position and check that the interface
111 // returns the correct index for that position.
112 QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
113 QAccessibleInterface *childAtInterface = interface->childAt(globalChildPos.x(), globalChildPos.y());
114 if (!childAtInterface) {
115 qWarning("tst_QAccessibility::verifyChild (childAt()):");
116 qWarning() << "Expected:" << childInterface;
117 qWarning() << "Actual: no child";
120 if (childAtInterface->object() != childInterface->object()) {
121 qWarning("tst_QAccessibility::verifyChild (childAt()):");
122 qWarning() << "Expected:" << childInterface;
123 qWarning() << "Actual: " << childAtInterface;
126 delete childInterface;
127 delete childAtInterface;
129 // QAccessibleInterface::rect():
130 // Calculate global child geometry and check that the interface
131 // returns a QRect which is equal to the calculated QRect.
132 const QRect expectedGlobalRect = QRect(globalChildPos, child->size());
133 if (expectedGlobalRect != rectFromInterface) {
134 qWarning("tst_QAccessibility::verifyChild (rect()):");
135 qWarning() << "Expected:" << expectedGlobalRect;
136 qWarning() << "Actual: " << rectFromInterface;
140 // Verify that the child is within its domain.
141 if (!domain.contains(rectFromInterface)) {
142 qWarning("tst_QAccessibility::verifyChild: Child is not within its domain.");
149 static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget)
151 if (!parentInterface || !childWidget)
153 QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(childWidget);
156 int index = parentInterface->indexOfChild(childInterface);
157 delete childInterface;
161 #define EXPECT(cond) \
163 if (!errorAt && !(cond)) { \
164 errorAt = __LINE__; \
165 qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
169 static int verifyHierarchy(QAccessibleInterface *iface)
172 static int treelevel = 0; // for error diagnostics
173 QAccessibleInterface *middleChild, *if2;
176 int middle = iface->childCount()/2 + 1;
177 if (iface->childCount() >= 2) {
178 middleChild = iface->child(middle - 1);
180 for (int i = 0; i < iface->childCount() && !errorAt; ++i) {
181 if2 = iface->child(i);
183 // navigate Ancestor...
184 QAccessibleInterface *parent = if2->parent();
185 EXPECT(iface->object() == parent->object());
188 // navigate Sibling...
189 // if (middleChild) {
190 // entry = if2->navigate(QAccessible::Sibling, middle, &if3);
191 // EXPECT(entry == 0 && if3->object() == middleChild->object());
194 // EXPECT(iface->indexOfChild(middleChild) == middle);
197 // verify children...
199 errorAt = verifyHierarchy(if2);
208 QRect childRect(QAccessibleInterface *iface, int index = 0)
210 QAccessibleInterface *child = iface->child(index);
211 QRect rect = child->rect();
216 class tst_QAccessibility : public QObject
220 tst_QAccessibility();
221 virtual ~tst_QAccessibility();
225 void cleanupTestCase();
231 void deletedWidget();
233 void statesStructTest();
234 void navigateHierarchy();
236 void navigateCovered();
237 void textAttributes();
242 void applicationTest();
243 void mainWindowTest();
245 void scrollBarTest();
247 void tabWidgetTest();
250 void doubleSpinBoxTest();
252 void textBrowserTest();
254 void mdiSubWindowTest();
256 void workspaceTest();
257 void dialogButtonBoxTest();
259 void rubberBandTest();
260 void abstractScrollAreaTest();
261 void scrollAreaTest();
267 void calendarWidgetTest();
268 void dockWidgetTest();
270 void accessibleName();
280 const double Q_PI = 3.14159265358979323846;
282 QString eventName(const int ev)
285 case 0x0001: return "SoundPlayed";
286 case 0x0002: return "Alert";
287 case 0x0003: return "ForegroundChanged";
288 case 0x0004: return "MenuStart";
289 case 0x0005: return "MenuEnd";
290 case 0x0006: return "PopupMenuStart";
291 case 0x0007: return "PopupMenuEnd";
292 case 0x000C: return "ContextHelpStart";
293 case 0x000D: return "ContextHelpEnd";
294 case 0x000E: return "DragDropStart";
295 case 0x000F: return "DragDropEnd";
296 case 0x0010: return "DialogStart";
297 case 0x0011: return "DialogEnd";
298 case 0x0012: return "ScrollingStart";
299 case 0x0013: return "ScrollingEnd";
300 case 0x0018: return "MenuCommand";
302 case 0x0116: return "TableModelChanged";
303 case 0x011B: return "TextCaretMoved";
305 case 0x8000: return "ObjectCreated";
306 case 0x8001: return "ObjectDestroyed";
307 case 0x8002: return "ObjectShow";
308 case 0x8003: return "ObjectHide";
309 case 0x8004: return "ObjectReorder";
310 case 0x8005: return "Focus";
311 case 0x8006: return "Selection";
312 case 0x8007: return "SelectionAdd";
313 case 0x8008: return "SelectionRemove";
314 case 0x8009: return "SelectionWithin";
315 case 0x800A: return "StateChanged";
316 case 0x800B: return "LocationChanged";
317 case 0x800C: return "NameChanged";
318 case 0x800D: return "DescriptionChanged";
319 case 0x800E: return "ValueChanged";
320 case 0x800F: return "ParentChanged";
321 case 0x80A0: return "HelpChanged";
322 case 0x80B0: return "DefaultActionChanged";
323 case 0x80C0: return "AcceleratorChanged";
324 default: return "Unknown Event";
328 QAccessible::State state(QWidget * const widget)
330 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
332 qWarning() << "Cannot get QAccessibleInterface for widget";
333 QAccessible::State state = (iface ? iface->state() : QAccessible::State());
338 class QtTestAccessibleWidget: public QWidget
342 QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
346 pal.setColor(backgroundRole(), Qt::black);//black is beautiful
352 class QtTestAccessibleWidgetIface: public QAccessibleWidget
355 QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
356 QString text(QAccessible::Text t) const
358 if (t == QAccessible::Help)
359 return QString::fromLatin1("Help yourself");
360 return QAccessibleWidget::text(t);
362 static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
364 if (key == "QtTestAccessibleWidget")
365 return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
370 tst_QAccessibility::tst_QAccessibility()
375 tst_QAccessibility::~tst_QAccessibility()
379 void tst_QAccessibility::onClicked()
384 void tst_QAccessibility::initTestCase()
386 QTestAccessibility::initialize();
387 QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
390 void tst_QAccessibility::cleanupTestCase()
392 QTestAccessibility::cleanup();
395 void tst_QAccessibility::init()
397 QTestAccessibility::clearEvents();
400 void tst_QAccessibility::cleanup()
402 const EventList list = QTestAccessibility::events();
403 if (!list.isEmpty()) {
404 qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
405 QString(QTest::currentTestFunction()).toAscii().constData());
406 for (int i = 0; i < list.count(); ++i)
407 qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
408 eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
410 QTestAccessibility::clearEvents();
413 void tst_QAccessibility::eventTest()
415 QPushButton* button = new QPushButton(0);
416 button->setObjectName(QString("Olaf"));
419 QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
420 button->setFocus(Qt::MouseFocusReason);
421 QTestAccessibility::clearEvents();
422 QTest::mouseClick(button, Qt::LeftButton, 0);
423 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
424 QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
426 button->setAccessibleName("Olaf the second");
427 QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
428 button->setAccessibleDescription("This is a button labeled Olaf");
429 QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
432 QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
437 void tst_QAccessibility::customWidget()
439 QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
441 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
443 QVERIFY(iface->isValid());
444 QCOMPARE(iface->object(), (QObject*)widget);
445 QCOMPARE(iface->object()->objectName(), QString("Heinz"));
446 QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
452 void tst_QAccessibility::deletedWidget()
454 QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
455 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
457 QVERIFY(iface->isValid());
458 QCOMPARE(iface->object(), (QObject*)widget);
462 QVERIFY(!iface->isValid());
466 void tst_QAccessibility::statesStructTest()
468 QAccessible::State s1;
469 QVERIFY(s1.unavailable == 0);
470 QVERIFY(s1.focusable == 0);
471 QVERIFY(s1.modal == 0);
473 QAccessible::State s2;
476 QVERIFY(!(s2 == s1));
479 s1 = QAccessible::State();
480 QVERIFY(!(s2 == s1));
483 QVERIFY(s1.busy == 1);
486 void tst_QAccessibility::sliderTest()
489 QSlider *slider = new QSlider(0);
490 slider->setObjectName(QString("Slidy"));
492 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider);
494 QVERIFY(iface->isValid());
496 QCOMPARE(iface->childCount(), 0);
497 QCOMPARE(iface->role(), QAccessible::Slider);
499 QAccessibleValueInterface *valueIface = iface->valueInterface();
500 QVERIFY(valueIface != 0);
501 QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum());
502 QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum());
503 slider->setValue(50);
504 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
506 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
507 slider->setValue(100);
508 QCOMPARE(valueIface->currentValue().toInt(), slider->value());
509 valueIface->setCurrentValue(77);
510 QCOMPARE(77, slider->value());
515 QTestAccessibility::clearEvents();
518 void tst_QAccessibility::navigateCovered()
521 QWidget *w = new QWidget(0);
522 w->setObjectName(QString("Harry"));
523 QWidget *w1 = new QWidget(w);
524 w1->setObjectName(QString("1"));
525 QWidget *w2 = new QWidget(w);
526 w2->setObjectName(QString("2"));
528 #if defined(Q_OS_UNIX)
529 QCoreApplication::processEvents();
533 w->setFixedSize(6, 6);
534 w1->setFixedSize(5, 5);
535 w2->setFixedSize(5, 5);
539 QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1);
540 QVERIFY(iface1 != 0);
541 QVERIFY(iface1->isValid());
542 QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2);
543 QVERIFY(iface2 != 0);
544 QVERIFY(iface2->isValid());
545 QAccessibleInterface *iface3 = 0;
547 QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1);
548 QVERIFY(iface3 == 0);
549 QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1);
550 QVERIFY(iface3 == 0);
551 QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1);
552 QVERIFY(iface3 == 0);
554 for (int loop = 0; loop < 2; ++loop) {
555 for (int x = 0; x < w->width(); ++x) {
556 for (int y = 0; y < w->height(); ++y) {
558 if (w1->geometry().intersects(w2->geometry())) {
559 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
560 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
561 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0);
562 QVERIFY(iface3 != 0);
563 QVERIFY(iface3->isValid());
564 QCOMPARE(iface3->object(), iface2->object());
565 delete iface3; iface3 = 0;
566 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0);
567 QVERIFY(iface3 != 0);
568 QVERIFY(iface3->isValid());
569 QCOMPARE(iface3->object(), iface1->object());
570 delete iface3; iface3 = 0;
572 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
573 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
574 QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1);
575 QVERIFY(iface3 == 0);
576 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
577 QVERIFY(iface3 == 0);
578 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
579 QVERIFY(iface3 == 0);
580 QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1);
581 QVERIFY(iface3 == 0);
586 // switch children for second loop
588 QAccessibleInterface *temp = iface1;
593 delete iface1; iface1 = 0;
594 delete iface2; iface2 = 0;
595 iface1 = QAccessible::queryAccessibleInterface(w1);
596 QVERIFY(iface1 != 0);
597 QVERIFY(iface1->isValid());
598 iface2 = QAccessible::queryAccessibleInterface(w2);
599 QVERIFY(iface2 != 0);
600 QVERIFY(iface2->isValid());
605 QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
606 QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
607 QVERIFY(!iface1->state().invisible);
609 QVERIFY(iface1->state().invisible);
610 QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
611 QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
612 QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
613 QVERIFY(iface3 == 0);
614 QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
615 QVERIFY(iface3 == 0);
617 delete iface1; iface1 = 0;
618 delete iface2; iface2 = 0;
621 QTestAccessibility::clearEvents();
624 void tst_QAccessibility::navigateHierarchy()
627 QWidget *w = new QWidget(0);
628 w->setObjectName(QString("Hans"));
630 QWidget *w1 = new QWidget(w);
631 w1->setObjectName(QString("1"));
633 QWidget *w2 = new QWidget(w);
634 w2->setObjectName(QString("2"));
636 QWidget *w3 = new QWidget(w);
637 w3->setObjectName(QString("3"));
639 QWidget *w31 = new QWidget(w3);
640 w31->setObjectName(QString("31"));
643 QAccessibleInterface *target = 0;
644 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w);
646 QVERIFY(iface->isValid());
648 target = iface->child(14);
649 QVERIFY(target == 0);
650 target = iface->child(-1);
651 QVERIFY(target == 0);
652 target = iface->child(0);
653 QAccessibleInterface *interfaceW1 = iface->child(0);
655 QVERIFY(target->isValid());
656 QCOMPARE(target->object(), (QObject*)w1);
657 QVERIFY(interfaceW1 != 0);
658 QVERIFY(interfaceW1->isValid());
659 QCOMPARE(interfaceW1->object(), (QObject*)w1);
661 delete iface; iface = 0;
663 iface = QAccessible::queryAccessibleInterface(w);
664 target = iface->child(2);
665 QVERIFY(target != 0);
666 QVERIFY(target->isValid());
667 QCOMPARE(target->object(), (QObject*)w3);
668 delete iface; iface = 0;
671 iface = target->child(1);
672 QCOMPARE(iface, (QAccessibleInterface*)0);
673 iface = target->child(0);
675 QVERIFY(iface->isValid());
676 QCOMPARE(iface->object(), (QObject*)w31);
678 iface = QAccessible::queryAccessibleInterface(w);
679 QAccessibleInterface *acc3 = iface->child(2);
680 target = acc3->child(0);
683 QCOMPARE(target->object(), (QObject*)w31);
685 iface = target->parent();
687 QVERIFY(iface->isValid());
688 QCOMPARE(iface->object(), (QObject*)w3);
689 delete iface; iface = 0;
690 delete target; target = 0;
694 QTestAccessibility::clearEvents();
697 #define QSETCOMPARE(thetypename, elements, otherelements) \
698 QCOMPARE((QSet<thetypename>() << elements), (QSet<thetypename>() << otherelements))
700 static QWidget *createWidgets()
702 QWidget *w = new QWidget();
704 QHBoxLayout *box = new QHBoxLayout(w);
707 box->addWidget(new QComboBox(w));
708 box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
709 box->addWidget(new QHeaderView(Qt::Vertical, w));
710 box->addWidget(new QTreeView(w));
711 box->addWidget(new QTreeWidget(w));
712 box->addWidget(new QListView(w));
713 box->addWidget(new QListWidget(w));
714 box->addWidget(new QTableView(w));
715 box->addWidget(new QTableWidget(w));
716 box->addWidget(new QCalendarWidget(w));
717 box->addWidget(new QDialogButtonBox(w));
718 box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
719 box->addWidget(new QFrame(w));
720 box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
721 box->addWidget(new QProgressBar(w));
722 box->addWidget(new QTabWidget(w));
723 box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
724 box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
725 box->addWidget(new QDial(w));
726 box->addWidget(new QScrollBar(w));
727 box->addWidget(new QSlider(w));
728 box->addWidget(new QDateTimeEdit(w));
729 box->addWidget(new QDoubleSpinBox(w));
730 box->addWidget(new QSpinBox(w));
731 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
732 box->addWidget(new QLCDNumber(w));
733 box->addWidget(new QStackedWidget(w));
734 box->addWidget(new QToolBox(w));
735 box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
736 box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
739 * QAbstractItemView, QGraphicsView, QScrollArea,
740 * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
741 * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
746 void tst_QAccessibility::accessibleName()
748 QWidget *toplevel = createWidgets();
750 #if defined(Q_OS_UNIX)
751 QCoreApplication::processEvents();
754 QLayout *lout = toplevel->layout();
755 for (int i = 0; i < lout->count(); i++) {
756 QLayoutItem *item = lout->itemAt(i);
757 QWidget *child = item->widget();
759 QString name = tr("Widget Name %1").arg(i);
760 child->setAccessibleName(name);
761 QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
762 QCOMPARE(acc->text(QAccessible::Name), name);
764 QString desc = tr("Widget Description %1").arg(i);
765 child->setAccessibleDescription(desc);
766 QCOMPARE(acc->text(QAccessible::Description), desc);
771 QTestAccessibility::clearEvents();
774 void tst_QAccessibility::textAttributes()
780 QString text("<html><head></head><body>"
781 "Hello, <b>this</b> is an <i><b>example</b> text</i>."
782 "<span style=\"font-family: monospace\">Multiple fonts are used.</span>"
783 "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used."
784 "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."
787 textEdit.setText(text);
788 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit);
790 QAccessibleTextInterface *textInterface=interface->textInterface();
792 QVERIFY(textInterface);
793 QCOMPARE(textInterface->characterCount(), 112);
795 attributes = textInterface->attributes(10, &startOffset, &endOffset);
796 QCOMPARE(startOffset, 7);
797 QCOMPARE(endOffset, 11);
798 attributes.prepend(';');
799 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
801 attributes = textInterface->attributes(18, &startOffset, &endOffset);
802 QCOMPARE(startOffset, 18);
803 QCOMPARE(endOffset, 25);
804 attributes.prepend(';');
805 QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
806 QVERIFY(attributes.contains(QLatin1String(";font-style:italic;")));
808 attributes = textInterface->attributes(34, &startOffset, &endOffset);
809 QCOMPARE(startOffset, 31);
810 QCOMPARE(endOffset, 55);
811 attributes.prepend(';');
812 QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";")));
814 attributes = textInterface->attributes(65, &startOffset, &endOffset);
815 QCOMPARE(startOffset, 64);
816 QCOMPARE(endOffset, 74);
817 attributes.prepend(';');
818 QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;")));
820 attributes = textInterface->attributes(110, &startOffset, &endOffset);
821 QCOMPARE(startOffset, 109);
822 QCOMPARE(endOffset, 111);
823 attributes.prepend(';');
824 QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);")));
825 QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);")));
828 void tst_QAccessibility::hideShowTest()
830 QWidget * const window = new QWidget();
831 QWidget * const child = new QWidget(window);
833 QVERIFY(state(window).invisible);
834 QVERIFY(state(child).invisible);
836 QTestAccessibility::clearEvents();
838 // show() and veryfy that both window and child are not invisible and get ObjectShow events.
840 QVERIFY(!state(window).invisible);
841 QVERIFY(!state(child).invisible);
842 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
843 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
844 QTestAccessibility::clearEvents();
846 // hide() and veryfy that both window and child are invisible and get ObjectHide events.
848 QVERIFY(state(window).invisible);
849 QVERIFY(state(child).invisible);
850 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
851 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
852 QTestAccessibility::clearEvents();
855 QTestAccessibility::clearEvents();
859 void tst_QAccessibility::actionTest()
862 QCOMPARE(QAccessibleActionInterface::pressAction(), QString(QStringLiteral("Press")));
864 QWidget *widget = new QWidget;
865 widget->setFocusPolicy(Qt::NoFocus);
868 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(widget);
870 QVERIFY(interface->isValid());
871 QAccessibleActionInterface *actions = interface->actionInterface();
874 // no actions by default, except when focusable
875 QCOMPARE(actions->actionNames(), QStringList());
876 widget->setFocusPolicy(Qt::StrongFocus);
877 QCOMPARE(actions->actionNames(), QStringList(QAccessibleActionInterface::setFocusAction()));
882 QTestAccessibility::clearEvents();
885 QPushButton *button = new QPushButton;
887 button->clearFocus();
888 QCOMPARE(button->hasFocus(), false);
889 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
890 QAccessibleActionInterface *actions = interface->actionInterface();
893 // Make sure the "primary action" press comes first!
894 QCOMPARE(actions->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
896 actions->doAction(QAccessibleActionInterface::setFocusAction());
898 QCOMPARE(button->hasFocus(), true);
900 connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
901 QCOMPARE(click_count, 0);
902 actions->doAction(QAccessibleActionInterface::pressAction());
904 QCOMPARE(click_count, 1);
909 QTestAccessibility::clearEvents();
912 void tst_QAccessibility::applicationTest()
914 QLatin1String name = QLatin1String("My Name");
915 qApp->setApplicationName(name);
916 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp);
917 QCOMPARE(interface->text(QAccessible::Name), name);
918 QCOMPARE(interface->role(), QAccessible::Application);
922 void tst_QAccessibility::mainWindowTest()
924 QMainWindow *mw = new QMainWindow;
925 mw->resize(300, 200);
926 mw->show(); // triggers layout
928 QLatin1String name = QLatin1String("I am the main window");
929 mw->setWindowTitle(name);
930 QTest::qWaitForWindowShown(mw);
931 QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
933 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
934 QCOMPARE(interface->text(QAccessible::Name), name);
935 QCOMPARE(interface->role(), QAccessible::Window);
938 QTestAccessibility::clearEvents();
941 class CounterButton : public QPushButton {
944 CounterButton(const QString& name, QWidget* parent)
945 : QPushButton(name, parent), clickCount(0)
947 connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount()));
951 void incClickCount() {
956 void tst_QAccessibility::buttonTest()
959 window.setLayout(new QVBoxLayout);
961 // Standard push button
962 CounterButton pushButton("Ok", &window);
965 QPushButton toggleButton("Toggle", &window);
966 toggleButton.setCheckable(true);
969 QCheckBox checkBox("Check me!", &window);
972 QCheckBox tristate("Tristate!", &window);
973 tristate.setTristate(true);
976 QRadioButton radio("Radio me!", &window);
978 // standard toolbutton
979 QToolButton toolbutton(&window);
980 toolbutton.setText("Tool");
981 toolbutton.setMinimumSize(20,20);
983 // standard toolbutton
984 QToolButton toggletool(&window);
985 toggletool.setCheckable(true);
986 toggletool.setText("Toggle");
987 toggletool.setMinimumSize(20,20);
990 QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton);
991 QAccessibleActionInterface* actionInterface = interface->actionInterface();
992 QVERIFY(actionInterface != 0);
993 QCOMPARE(interface->role(), QAccessible::PushButton);
995 // buttons only have a click action
996 QCOMPARE(actionInterface->actionNames().size(), 2);
997 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
998 QCOMPARE(pushButton.clickCount, 0);
999 actionInterface->doAction(QAccessibleActionInterface::pressAction());
1001 QCOMPARE(pushButton.clickCount, 1);
1004 // test toggle button
1005 interface = QAccessible::queryAccessibleInterface(&toggleButton);
1006 actionInterface = interface->actionInterface();
1007 QCOMPARE(interface->role(), QAccessible::CheckBox);
1008 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1009 QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
1010 QVERIFY(!toggleButton.isChecked());
1011 QVERIFY(!interface->state().checked);
1012 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1014 QVERIFY(toggleButton.isChecked());
1015 QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
1016 QVERIFY(interface->state().checked);
1020 // test menu push button
1021 QAction *foo = new QAction("Foo", 0);
1022 foo->setShortcut(QKeySequence("Ctrl+F"));
1023 QMenu *menu = new QMenu();
1024 menu->addAction(foo);
1025 QPushButton menuButton;
1026 menuButton.setMenu(menu);
1028 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
1029 QCOMPARE(interface->role(), QAccessible::ButtonMenu);
1030 QVERIFY(interface->state().hasPopup);
1031 QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction());
1032 // showing the menu enters a new event loop...
1033 // interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1034 // QTest::qWait(500);
1040 interface = QAccessible::queryAccessibleInterface(&checkBox);
1041 actionInterface = interface->actionInterface();
1042 QCOMPARE(interface->role(), QAccessible::CheckBox);
1043 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1044 QVERIFY(!interface->state().checked);
1045 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1047 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
1048 QVERIFY(interface->state().checked);
1049 QVERIFY(checkBox.isChecked());
1053 interface = QAccessible::queryAccessibleInterface(&radio);
1054 actionInterface = interface->actionInterface();
1055 QCOMPARE(interface->role(), QAccessible::RadioButton);
1056 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1057 QVERIFY(!interface->state().checked);
1058 actionInterface->doAction(QAccessibleActionInterface::checkAction());
1060 QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1061 QVERIFY(interface->state().checked);
1062 QVERIFY(checkBox.isChecked());
1065 // // test standard toolbutton
1066 // QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
1067 // QCOMPARE(test->role(), QAccessible::PushButton);
1068 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1069 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1070 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1073 // // toggle tool button
1074 // QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test));
1075 // QCOMPARE(test->role(), QAccessible::CheckBox);
1076 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1077 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check"));
1078 // QCOMPARE(test->state(), (int)QAccessible::Normal);
1079 // QVERIFY(test->doAction(QAccessible::Press, 0));
1080 // QTest::qWait(500);
1081 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck"));
1082 // QCOMPARE(test->state(), (int)QAccessible::Checked);
1085 // // test menu toolbutton
1086 // QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test));
1087 // QCOMPARE(test->role(), QAccessible::ButtonMenu);
1088 // QCOMPARE(test->defaultAction(0), 1);
1089 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open"));
1090 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1091 // QCOMPARE(test->actionCount(0), 1);
1092 // QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
1095 // // test split menu toolbutton
1096 // QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
1097 // QCOMPARE(test->childCount(), 2);
1098 // QCOMPARE(test->role(), QAccessible::ButtonDropDown);
1099 // QCOMPARE(test->role(1), QAccessible::PushButton);
1100 // QCOMPARE(test->role(2), QAccessible::ButtonMenu);
1101 // QCOMPARE(test->defaultAction(0), QAccessible::Press);
1102 // QCOMPARE(test->defaultAction(1), QAccessible::Press);
1103 // QCOMPARE(test->defaultAction(2), QAccessible::Press);
1104 // QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1105 // QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1106 // QCOMPARE(test->actionCount(0), 1);
1107 // QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open"));
1108 // QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press"));
1109 // QCOMPARE(test->state(1), (int)QAccessible::Normal);
1110 // QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
1111 // QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
1114 QTestAccessibility::clearEvents();
1117 void tst_QAccessibility::scrollBarTest()
1119 QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
1120 QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
1121 QVERIFY(scrollBarInterface);
1122 QVERIFY(scrollBarInterface->state().invisible);
1123 scrollBar->resize(200, 50);
1125 QVERIFY(!scrollBarInterface->state().invisible);
1126 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
1127 QTestAccessibility::clearEvents();
1130 QVERIFY(scrollBarInterface->state().invisible);
1131 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
1132 QTestAccessibility::clearEvents();
1134 // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
1136 scrollBar->setMinimum(11);
1137 scrollBar->setMaximum(111);
1139 QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface();
1140 QVERIFY(valueIface != 0);
1141 QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum());
1142 QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum());
1143 scrollBar->setValue(50);
1144 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1145 scrollBar->setValue(0);
1146 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1147 scrollBar->setValue(100);
1148 QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1149 valueIface->setCurrentValue(77);
1150 QCOMPARE(77, scrollBar->value());
1152 const QRect scrollBarRect = scrollBarInterface->rect();
1153 QVERIFY(scrollBarRect.isValid());
1155 delete scrollBarInterface;
1158 QTestAccessibility::clearEvents();
1161 void tst_QAccessibility::tabTest()
1163 QTabBar *tabBar = new QTabBar();
1166 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar);
1168 QCOMPARE(interface->childCount(), 2);
1170 // Test that the Invisible bit for the navigation buttons gets set
1171 // and cleared correctly.
1172 QAccessibleInterface *leftButton = interface->child(0);
1173 QCOMPARE(leftButton->role(), QAccessible::PushButton);
1174 QVERIFY(leftButton->state().invisible);
1178 for (int i = 0; i < lots; ++i)
1179 tabBar->addTab("Foo");
1181 QAccessibleInterface *child1 = interface->child(0);
1182 QAccessibleInterface *child2 = interface->child(1);
1184 QCOMPARE(child1->role(), QAccessible::PageTab);
1186 QCOMPARE(child2->role(), QAccessible::PageTab);
1188 QVERIFY((child1->state().invisible) == false);
1191 QCoreApplication::processEvents();
1194 QVERIFY(child1->state().invisible);
1197 tabBar->setCurrentIndex(0);
1199 // Test that sending a focus action to a tab does not select it.
1200 // child2->doAction(QAccessible::Focus, 2, QVariantList());
1201 QCOMPARE(tabBar->currentIndex(), 0);
1203 // Test that sending a press action to a tab selects it.
1204 QVERIFY(child2->actionInterface());
1205 QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1206 QCOMPARE(tabBar->currentIndex(), 0);
1207 child2->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
1208 QCOMPARE(tabBar->currentIndex(), 1);
1214 QTestAccessibility::clearEvents();
1217 void tst_QAccessibility::tabWidgetTest()
1219 QTabWidget *tabWidget = new QTabWidget();
1222 // the interface for the tab is just a container for tabbar and stacked widget
1223 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget);
1225 QCOMPARE(interface->childCount(), 2);
1226 QCOMPARE(interface->role(), QAccessible::Client);
1228 // Create pages, check navigation
1229 QLabel *label1 = new QLabel("Page 1", tabWidget);
1230 tabWidget->addTab(label1, "Tab 1");
1231 QLabel *label2 = new QLabel("Page 2", tabWidget);
1232 tabWidget->addTab(label2, "Tab 2");
1234 QCOMPARE(interface->childCount(), 2);
1236 QAccessibleInterface* tabBarInterface = 0;
1237 // there is no special logic to sort the children, so the contents will be 1, the tab bar 2
1238 tabBarInterface = interface->child(1);
1239 QVERIFY(tabBarInterface);
1240 QCOMPARE(tabBarInterface->childCount(), 4);
1241 QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList);
1243 QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0);
1244 QVERIFY(tabButton1Interface);
1245 QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab);
1246 QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1"));
1248 QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1);
1249 QVERIFY(tabButton1Interface);
1250 QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab);
1251 QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2"));
1253 QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2);
1254 QVERIFY(tabButtonLeft);
1255 QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton);
1256 QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left"));
1258 QAccessibleInterface* tabButtonRight = tabBarInterface->child(3);
1259 QVERIFY(tabButtonRight);
1260 QCOMPARE(tabButtonRight->role(), QAccessible::PushButton);
1261 QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right"));
1262 delete tabButton1Interface;
1263 delete tabButton2Interface;
1264 delete tabButtonLeft;
1265 delete tabButtonRight;
1267 QAccessibleInterface* stackWidgetInterface = interface->child(0);
1268 QVERIFY(stackWidgetInterface);
1269 QCOMPARE(stackWidgetInterface->childCount(), 2);
1270 QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane);
1272 QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0);
1273 QVERIFY(stackChild1Interface);
1275 QCOMPARE(stackChild1Interface->childCount(), 0);
1277 QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText);
1278 QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1"));
1279 QCOMPARE(label1, stackChild1Interface->object());
1281 // Navigation in stack widgets should be consistent
1282 QAccessibleInterface* parent = stackChild1Interface->parent();
1285 QCOMPARE(parent->childCount(), 2);
1287 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1290 QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1);
1291 QVERIFY(stackChild2Interface);
1292 QCOMPARE(stackChild2Interface->childCount(), 0);
1293 QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText);
1294 QCOMPARE(label2, stackChild2Interface->object());
1295 QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name));
1297 parent = stackChild2Interface->parent();
1300 QCOMPARE(parent->childCount(), 2);
1302 QCOMPARE(parent->role(), QAccessible::LayeredPane);
1305 delete tabBarInterface;
1306 delete stackChild1Interface;
1307 delete stackChild2Interface;
1308 delete stackWidgetInterface;
1311 QTestAccessibility::clearEvents();
1314 void tst_QAccessibility::menuTest()
1318 mw.resize(300, 200);
1319 QMenu *file = mw.menuBar()->addMenu("&File");
1320 QMenu *fileNew = file->addMenu("&New...");
1321 fileNew->menuAction()->setShortcut(tr("Ctrl+N"));
1322 fileNew->addAction("Text file");
1323 fileNew->addAction("Image file");
1324 file->addAction("&Open")->setShortcut(tr("Ctrl+O"));
1325 file->addAction("&Save")->setShortcut(tr("Ctrl+S"));
1326 file->addSeparator();
1327 file->addAction("E&xit")->setShortcut(tr("Alt+F4"));
1329 QMenu *edit = mw.menuBar()->addMenu("&Edit");
1330 edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z"));
1331 edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y"));
1332 edit->addSeparator();
1333 edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X"));
1334 edit->addAction("&Copy")->setShortcut(tr("Ctrl+C"));
1335 edit->addAction("&Paste")->setShortcut(tr("Ctrl+V"));
1336 edit->addAction("&Delete")->setShortcut(tr("Del"));
1337 edit->addSeparator();
1338 edit->addAction("Pr&operties");
1340 mw.menuBar()->addSeparator();
1342 QMenu *help = mw.menuBar()->addMenu("&Help");
1343 help->addAction("&Contents");
1344 help->addAction("&About");
1346 mw.menuBar()->addAction("Action!");
1348 mw.show(); // triggers layout
1351 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
1352 QCOMPARE(verifyHierarchy(interface), 0);
1355 QCOMPARE(interface->childCount(), 5);
1356 QCOMPARE(interface->role(), QAccessible::MenuBar);
1358 QAccessibleInterface *iFile = interface->child(0);
1359 QAccessibleInterface *iEdit = interface->child(1);
1360 QAccessibleInterface *iSeparator = interface->child(2);
1361 QAccessibleInterface *iHelp = interface->child(3);
1362 QAccessibleInterface *iAction = interface->child(4);
1364 QCOMPARE(iFile->role(), QAccessible::MenuItem);
1365 QCOMPARE(iEdit->role(), QAccessible::MenuItem);
1366 QCOMPARE(iSeparator->role(), QAccessible::Separator);
1367 QCOMPARE(iHelp->role(), QAccessible::MenuItem);
1368 QCOMPARE(iAction->role(), QAccessible::MenuItem);
1371 if (!IsValidCEPlatform())
1372 QSKIP("Tests do not work on Mobile platforms due to native menus");
1374 QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft());
1375 QCOMPARE(interface->rect().size(), mw.menuBar()->size());
1377 QVERIFY(interface->rect().contains(iFile->rect()));
1378 QVERIFY(interface->rect().contains(iEdit->rect()));
1379 // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible
1380 QVERIFY(interface->rect().contains(iHelp->rect()));
1381 QVERIFY(interface->rect().contains(iAction->rect()));
1384 QCOMPARE(iFile->text(QAccessible::Name), QString("File"));
1385 QCOMPARE(iEdit->text(QAccessible::Name), QString("Edit"));
1386 QCOMPARE(iSeparator->text(QAccessible::Name), QString());
1387 QCOMPARE(iHelp->text(QAccessible::Name), QString("Help"));
1388 QCOMPARE(iAction->text(QAccessible::Name), QString("Action!"));
1390 // TODO: Currently not working, task to fix is #100019.
1392 QCOMPARE(iFile->text(QAccessible::Accelerator), tr("Alt+F"));
1393 QCOMPARE(iEdit->text(QAccessible::Accelerator), tr("Alt+E"));
1394 QCOMPARE(iSeparator->text(QAccessible::Accelerator), QString());
1395 QCOMPARE(iHelp->text(QAccessible::Accelerator), tr("Alt+H"));
1396 QCOMPARE(iAction->text(QAccessible::Accelerator), QString());
1399 QVERIFY(iFile->actionInterface());
1401 QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1402 QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList());
1403 QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1404 QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1406 bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu);
1407 int menuFadeDelay = 300;
1408 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1410 QTest::qWait(menuFadeDelay);
1411 QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible());
1412 iEdit->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1414 QTest::qWait(menuFadeDelay);
1415 QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible());
1416 iHelp->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1418 QTest::qWait(menuFadeDelay);
1419 QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible());
1420 iAction->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1422 QTest::qWait(menuFadeDelay);
1423 QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible());
1425 QVERIFY(interface->actionInterface());
1426 QCOMPARE(interface->actionInterface()->actionNames(), QStringList());
1428 interface = QAccessible::queryAccessibleInterface(file);
1429 QCOMPARE(interface->childCount(), 5);
1430 QCOMPARE(interface->role(), QAccessible::PopupMenu);
1432 QAccessibleInterface *iFileNew = interface->child(0);
1433 QAccessibleInterface *iFileOpen = interface->child(1);
1434 QAccessibleInterface *iFileSave = interface->child(2);
1435 QAccessibleInterface *iFileSeparator = interface->child(3);
1436 QAccessibleInterface *iFileExit = interface->child(4);
1438 QCOMPARE(iFileNew->role(), QAccessible::MenuItem);
1439 QCOMPARE(iFileOpen->role(), QAccessible::MenuItem);
1440 QCOMPARE(iFileSave->role(), QAccessible::MenuItem);
1441 QCOMPARE(iFileSeparator->role(), QAccessible::Separator);
1442 QCOMPARE(iFileExit->role(), QAccessible::MenuItem);
1443 QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1444 QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1445 QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1446 QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList());
1447 QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1449 QAccessibleInterface *iface = 0;
1450 QAccessibleInterface *iface2 = 0;
1452 // traverse siblings with navigate(Sibling, ...)
1454 iface = interface->child(0);
1456 QCOMPARE(iface->role(), QAccessible::MenuItem);
1458 QAccessible::Role fileRoles[5] = {
1459 QAccessible::MenuItem,
1460 QAccessible::MenuItem,
1461 QAccessible::MenuItem,
1462 QAccessible::Separator,
1463 QAccessible::MenuItem
1465 for (int child = 0; child < 5; ++child) {
1466 iface2 = interface->child(child);
1468 QCOMPARE(iface2->role(), fileRoles[child]);
1473 // traverse menu items with navigate(Down, ...)
1474 iface = interface->child(0);
1476 QCOMPARE(iface->role(), QAccessible::MenuItem);
1478 for (int child = 0; child < 4; ++child) {
1479 entry = iface->navigate(QAccessible::Down, 1, &iface2);
1484 QCOMPARE(iface->role(), fileRoles[child + 1]);
1488 // traverse menu items with navigate(Up, ...)
1489 iface = interface->child(interface->childCount() - 1);
1491 QCOMPARE(iface->role(), QAccessible::MenuItem);
1493 for (int child = 3; child >= 0; --child) {
1494 entry = iface->navigate(QAccessible::Up, 1, &iface2);
1499 QCOMPARE(iface->role(), fileRoles[child]);
1504 iface = interface->child(0);
1506 QCOMPARE(iface->role(), QAccessible::MenuItem);
1509 iface2 = iface->child(0);
1514 QCOMPARE(iface->role(), QAccessible::PopupMenu);
1516 // "Text file" menu item
1517 iface2 = iface->child(0);
1521 QCOMPARE(iface->role(), QAccessible::MenuItem);
1525 // move mouse pointer away, since that might influence the
1527 QTest::mouseMove(&mw, QPoint(-1, -1));
1530 QTest::qWait(menuFadeDelay);
1532 iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1533 iFileNew->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1535 QVERIFY(file->isVisible());
1536 QVERIFY(fileNew->isVisible());
1537 QVERIFY(!edit->isVisible());
1538 QVERIFY(!help->isVisible());
1540 QTestAccessibility::clearEvents();
1547 delete iFileSeparator;
1550 // Do not crash if the menu don't have a parent
1551 QMenu *menu = new QMenu;
1552 menu->addAction(QLatin1String("one"));
1553 menu->addAction(QLatin1String("two"));
1554 menu->addAction(QLatin1String("three"));
1555 iface = QAccessible::queryAccessibleInterface(menu);
1556 iface2 = iface->parent();
1558 QCOMPARE(iface2->role(), QAccessible::Application);
1566 QTestAccessibility::clearEvents();
1569 void tst_QAccessibility::spinBoxTest()
1571 QSpinBox * const spinBox = new QSpinBox();
1572 spinBox->setValue(3);
1575 QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox);
1577 QCOMPARE(interface->role(), QAccessible::SpinBox);
1579 const QRect widgetRect = spinBox->geometry();
1580 const QRect accessibleRect = interface->rect();
1581 QCOMPARE(accessibleRect, widgetRect);
1582 QCOMPARE(interface->text(QAccessible::Value), QLatin1String("3"));
1584 // one child, the line edit
1585 const int numChildren = interface->childCount();
1586 QCOMPARE(numChildren, 1);
1587 QAccessibleInterface *lineEdit = interface->child(0);
1589 QCOMPARE(lineEdit->role(), QAccessible::EditableText);
1590 QCOMPARE(lineEdit->text(QAccessible::Value), QLatin1String("3"));
1593 QVERIFY(interface->valueInterface());
1594 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3);
1595 interface->valueInterface()->setCurrentValue(23);
1596 QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23);
1597 QCOMPARE(spinBox->value(), 23);
1599 spinBox->setFocus();
1600 QTestAccessibility::clearEvents();
1601 QTest::keyPress(spinBox, Qt::Key_Up);
1603 EventList events = QTestAccessibility::events();
1604 QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
1605 QVERIFY(events.contains(expectedEvent));
1607 QTestAccessibility::clearEvents();
1610 void tst_QAccessibility::doubleSpinBoxTest()
1612 QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox;
1613 doubleSpinBox->show();
1615 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
1618 const QRect widgetRect = doubleSpinBox->geometry();
1619 const QRect accessibleRect = interface->rect();
1620 QCOMPARE(accessibleRect, widgetRect);
1622 // Test that we get valid rects for all the spinbox child interfaces.
1623 const int numChildren = interface->childCount();
1624 for (int i = 0; i < numChildren; ++i) {
1625 QAccessibleInterface *childIface = interface->child(i);
1626 const QRect childRect = childIface->rect();
1627 QVERIFY(childRect.isValid());
1631 delete doubleSpinBox;
1632 QTestAccessibility::clearEvents();
1635 void tst_QAccessibility::textEditTest()
1641 QString text = "hello world\nhow are you today?\n";
1645 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
1646 QCOMPARE(iface->text(QAccessible::Value), text);
1647 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1648 QCOMPARE(startOffset, 6);
1649 QCOMPARE(endOffset, 11);
1650 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1651 QCOMPARE(startOffset, 12);
1652 QCOMPARE(endOffset, 30);
1653 QCOMPARE(iface->textInterface()->characterCount(), 31);
1654 QFontMetrics fm(edit.font());
1655 QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
1656 QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
1657 QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
1659 QTestAccessibility::clearEvents();
1662 void tst_QAccessibility::textBrowserTest()
1665 QTextBrowser textBrowser;
1666 QString text = QLatin1String("Hello world\nhow are you today?\n");
1667 textBrowser.setText(text);
1670 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
1672 QCOMPARE(iface->role(), QAccessible::StaticText);
1673 QCOMPARE(iface->text(QAccessible::Value), text);
1676 QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1677 QCOMPARE(startOffset, 6);
1678 QCOMPARE(endOffset, 11);
1679 QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1680 QCOMPARE(startOffset, 12);
1681 QCOMPARE(endOffset, 30);
1682 QCOMPARE(iface->textInterface()->characterCount(), 31);
1684 QTestAccessibility::clearEvents();
1687 void tst_QAccessibility::mdiAreaTest()
1691 mdiArea.resize(400,300);
1693 const int subWindowCount = 3;
1694 for (int i = 0; i < subWindowCount; ++i)
1695 mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show();
1697 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1698 QCOMPARE(subWindows.count(), subWindowCount);
1700 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea);
1702 QCOMPARE(interface->childCount(), subWindowCount);
1704 // Right, right, right, ...
1705 for (int i = 0; i < subWindowCount; ++i) {
1706 QAccessibleInterface *destination = 0;
1707 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
1708 if (i == subWindowCount - 1) {
1709 QVERIFY(!destination);
1710 QCOMPARE(index, -1);
1712 QVERIFY(destination);
1714 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
1719 // Left, left, left, ...
1720 for (int i = subWindowCount; i > 0; --i) {
1721 QAccessibleInterface *destination = 0;
1722 int index = interface->navigate(QAccessible::Left, i, &destination);
1724 QVERIFY(!destination);
1725 QCOMPARE(index, -1);
1727 QVERIFY(destination);
1729 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
1733 // ### Add test for Up and Down.
1736 QTestAccessibility::clearEvents();
1739 void tst_QAccessibility::mdiSubWindowTest()
1744 qApp->setActiveWindow(&mdiArea);
1745 #if defined(Q_OS_UNIX)
1746 QCoreApplication::processEvents();
1750 bool isSubWindowsPlacedNextToEachOther = false;
1751 const int subWindowCount = 5;
1752 for (int i = 0; i < subWindowCount; ++i) {
1753 QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
1755 // Parts of this test requires that the sub windows are placed next
1756 // to each other. In order to achieve that QMdiArea must have
1757 // a width which is larger than subWindow->width() * subWindowCount.
1759 int minimumWidth = window->width() * subWindowCount + 20;
1760 mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0)));
1761 #if defined(Q_OS_UNIX)
1762 QCoreApplication::processEvents();
1765 if (mdiArea.width() >= minimumWidth)
1766 isSubWindowsPlacedNextToEachOther = true;
1770 QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1771 QCOMPARE(subWindows.count(), subWindowCount);
1773 QMdiSubWindow *testWindow = subWindows.at(3);
1774 QVERIFY(testWindow);
1775 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow);
1779 QCOMPARE(interface->childCount(), 1);
1782 QCOMPARE(interface->text(QAccessible::Name), QString());
1783 testWindow->setWindowTitle(QLatin1String("ReplaceMe"));
1784 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("ReplaceMe"));
1785 interface->setText(QAccessible::Name, QLatin1String("TitleSetOnWindow"));
1786 QCOMPARE(interface->text(QAccessible::Name), QLatin1String("TitleSetOnWindow"));
1788 mdiArea.setActiveSubWindow(testWindow);
1791 QAccessible::State state;
1792 state.focusable = true;
1793 state.focused = true;
1794 state.movable = true;
1795 state.sizeable = true;
1797 QCOMPARE(interface->state(), state);
1798 const QRect originalGeometry = testWindow->geometry();
1799 testWindow->showMaximized();
1800 state.sizeable = false;
1801 state.movable = false;
1802 QCOMPARE(interface->state(), state);
1803 testWindow->showNormal();
1804 testWindow->move(-10, 0);
1805 QVERIFY(interface->state().offscreen);
1806 testWindow->setVisible(false);
1807 QVERIFY(interface->state().invisible);
1808 testWindow->setVisible(true);
1809 testWindow->setEnabled(false);
1810 QVERIFY(interface->state().unavailable);
1811 testWindow->setEnabled(true);
1812 qApp->setActiveWindow(&mdiArea);
1813 mdiArea.setActiveSubWindow(testWindow);
1814 testWindow->setFocus();
1815 QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
1816 QVERIFY(interface->state().focused);
1817 testWindow->setGeometry(originalGeometry);
1819 if (isSubWindowsPlacedNextToEachOther) {
1820 // This part of the test can only be run if the sub windows are
1821 // placed next to each other.
1822 QAccessibleInterface *destination = interface->child(0);
1823 QVERIFY(destination);
1824 QCOMPARE(destination->object(), (QObject*)testWindow->widget());
1826 QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0);
1827 QVERIFY(destination);
1828 QCOMPARE(destination->object(), (QObject*)subWindows.at(2));
1830 QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0);
1831 QVERIFY(destination);
1832 QCOMPARE(destination->object(), (QObject*)subWindows.at(4));
1837 const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0));
1838 QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size()));
1840 QCOMPARE(interface->rect(), QRect());
1841 QCOMPARE(childRect(interface), QRect());
1842 testWindow->showMinimized();
1843 QCOMPARE(childRect(interface), QRect());
1844 testWindow->showNormal();
1845 testWindow->widget()->hide();
1846 QCOMPARE(childRect(interface), QRect());
1847 testWindow->widget()->show();
1848 const QRect widgetGeometry = testWindow->contentsRect();
1849 const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
1850 globalPos.y() + widgetGeometry.y());
1851 QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
1854 QCOMPARE(interface->childAt(-10, 0), static_cast<QAccessibleInterface*>(0));
1855 QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), static_cast<QAccessibleInterface*>(0));
1856 QAccessibleInterface *child = interface->childAt(globalWidgetPos.x(), globalWidgetPos.y());
1857 QCOMPARE(child->role(), QAccessible::PushButton);
1858 QCOMPARE(child->text(QAccessible::Name), QString("QAccessibilityTest"));
1860 testWindow->widget()->hide();
1861 QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), static_cast<QAccessibleInterface*>(0));
1864 QTestAccessibility::clearEvents();
1867 void tst_QAccessibility::lineEditTest()
1869 QLineEdit *le = new QLineEdit;
1870 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
1874 QApplication::processEvents();
1875 QCOMPARE(iface->childCount(), 0);
1876 QVERIFY(iface->state().sizeable);
1877 QVERIFY(iface->state().movable);
1878 QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
1879 QVERIFY(iface->state().selectable);
1880 QVERIFY(iface->state().hasPopup);
1881 QCOMPARE(bool(iface->state().focused), le->hasFocus());
1883 QString secret(QLatin1String("secret"));
1884 le->setText(secret);
1885 le->setEchoMode(QLineEdit::Normal);
1886 QVERIFY(!(iface->state().passwordEdit));
1887 QCOMPARE(iface->text(QAccessible::Value), secret);
1888 le->setEchoMode(QLineEdit::NoEcho);
1889 QVERIFY(iface->state().passwordEdit);
1890 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1891 le->setEchoMode(QLineEdit::Password);
1892 QVERIFY(iface->state().passwordEdit);
1893 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1894 le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
1895 QVERIFY(iface->state().passwordEdit);
1896 QVERIFY(iface->text(QAccessible::Value).isEmpty());
1897 le->setEchoMode(QLineEdit::Normal);
1898 QVERIFY(!(iface->state().passwordEdit));
1899 QCOMPARE(iface->text(QAccessible::Value), secret);
1901 QWidget *toplevel = new QWidget;
1902 le->setParent(toplevel);
1904 QApplication::processEvents();
1905 QVERIFY(!(iface->state().sizeable));
1906 QVERIFY(!(iface->state().movable));
1907 QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
1908 QVERIFY(iface->state().selectable);
1909 QVERIFY(iface->state().hasPopup);
1910 QCOMPARE(bool(iface->state().focused), le->hasFocus());
1912 QLineEdit *le2 = new QLineEdit(toplevel);
1915 le2->activateWindow();
1917 le->setFocus(Qt::TabFocusReason);
1918 QTestAccessibility::clearEvents();
1919 le2->setFocus(Qt::TabFocusReason);
1920 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
1922 le->setText(QLatin1String("500"));
1923 le->setValidator(new QIntValidator());
1924 iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
1925 QCOMPARE(le->text(), QLatin1String("500"));
1930 QTestAccessibility::clearEvents();
1933 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";
1934 QLineEdit *le3 = new QLineEdit(cite, toplevel);
1935 iface = QAccessible::queryAccessibleInterface(le3);
1936 QAccessibleTextInterface* textIface = iface->textInterface();
1938 le3->setCursorPosition(3);
1939 QCOMPARE(textIface->cursorPosition(), 3);
1940 QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
1941 QCOMPARE(textIface->selectionCount(), 0);
1942 QTestAccessibility::clearEvents();
1945 QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
1946 QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
1949 QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString());
1950 QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" "));
1954 QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a"));
1957 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w"));
1958 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y"));
1960 QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
1964 QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
1965 QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
1966 QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
1967 QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
1968 QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
1970 QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
1971 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
1972 QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
1976 QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
1977 QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. "));
1979 QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite);
1981 QCOMPARE(end, cite.length());
1982 QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
1983 QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
1987 QTestAccessibility::clearEvents();
1990 void tst_QAccessibility::workspaceTest()
1993 QWorkspace workspace;
1994 workspace.resize(400,300);
1996 const int subWindowCount = 3;
1997 for (int i = 0; i < subWindowCount; ++i) {
1998 QWidget *window = workspace.addWindow(new QWidget);
2000 window->move(window->x() + 1, window->y());
2002 window->resize(70, window->height());
2005 QWidgetList subWindows = workspace.windowList();
2006 QCOMPARE(subWindows.count(), subWindowCount);
2008 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
2010 QCOMPARE(interface->childCount(), subWindowCount);
2012 // Right, right, right, ...
2013 for (int i = 0; i < subWindowCount; ++i) {
2014 QAccessibleInterface *destination = 0;
2015 int index = interface->navigate(QAccessible::Right, i + 1, &destination);
2016 if (i == subWindowCount - 1) {
2017 QVERIFY(!destination);
2018 QCOMPARE(index, -1);
2020 QVERIFY(destination);
2022 QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
2027 // Left, left, left, ...
2028 for (int i = subWindowCount; i > 0; --i) {
2029 QAccessibleInterface *destination = 0;
2030 int index = interface->navigate(QAccessible::Left, i, &destination);
2032 QVERIFY(!destination);
2033 QCOMPARE(index, -1);
2035 QVERIFY(destination);
2037 QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
2041 // ### Add test for Up and Down.
2044 QTestAccessibility::clearEvents();
2047 bool accessibleInterfaceLeftOf(const QAccessibleInterface *a1, const QAccessibleInterface *a2)
2049 return a1->rect().x() < a2->rect().x();
2052 bool accessibleInterfaceAbove(const QAccessibleInterface *a1, const QAccessibleInterface *a2)
2054 return a1->rect().y() < a2->rect().y();
2057 void tst_QAccessibility::dialogButtonBoxTest()
2060 QDialogButtonBox box(QDialogButtonBox::Reset |
2061 QDialogButtonBox::Help |
2062 QDialogButtonBox::Ok, Qt::Horizontal);
2065 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2068 #if defined(Q_OS_UNIX)
2069 QCoreApplication::processEvents();
2073 QApplication::processEvents();
2074 QCOMPARE(iface->childCount(), 3);
2075 QCOMPARE(iface->role(), QAccessible::Grouping);
2076 QStringList actualOrder;
2077 QAccessibleInterface *child;
2078 child = iface->child(0);
2079 QCOMPARE(child->role(), QAccessible::PushButton);
2081 QVector<QAccessibleInterface *> buttons;
2082 for (int i = 0; i < iface->childCount(); ++i)
2083 buttons << iface->child(i);
2085 qSort(buttons.begin(), buttons.end(), accessibleInterfaceLeftOf);
2087 for (int i = 0; i < buttons.count(); ++i)
2088 actualOrder << buttons.at(i)->text(QAccessible::Name);
2090 QStringList expectedOrder;
2091 QDialogButtonBox::ButtonLayout btnlout =
2092 QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout));
2094 case QDialogButtonBox::WinLayout:
2095 expectedOrder << QDialogButtonBox::tr("Reset")
2096 << QDialogButtonBox::tr("OK")
2097 << QDialogButtonBox::tr("Help");
2099 case QDialogButtonBox::GnomeLayout:
2100 case QDialogButtonBox::KdeLayout:
2101 case QDialogButtonBox::MacLayout:
2102 expectedOrder << QDialogButtonBox::tr("Help")
2103 << QDialogButtonBox::tr("Reset")
2104 << QDialogButtonBox::tr("OK");
2107 QCOMPARE(actualOrder, expectedOrder);
2109 QApplication::processEvents();
2110 QTestAccessibility::clearEvents();
2114 QDialogButtonBox box(QDialogButtonBox::Reset |
2115 QDialogButtonBox::Help |
2116 QDialogButtonBox::Ok, Qt::Horizontal);
2119 // Test up and down navigation
2120 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2122 box.setOrientation(Qt::Vertical);
2124 #if defined(Q_OS_UNIX)
2125 QCoreApplication::processEvents();
2129 QApplication::processEvents();
2130 QStringList actualOrder;
2132 QVector<QAccessibleInterface *> buttons;
2133 for (int i = 0; i < iface->childCount(); ++i)
2134 buttons << iface->child(i);
2136 qSort(buttons.begin(), buttons.end(), accessibleInterfaceAbove);
2138 for (int i = 0; i < buttons.count(); ++i)
2139 actualOrder << buttons.at(i)->text(QAccessible::Name);
2141 QStringList expectedOrder;
2142 expectedOrder << QDialogButtonBox::tr("OK")
2143 << QDialogButtonBox::tr("Reset")
2144 << QDialogButtonBox::tr("Help");
2146 QCOMPARE(actualOrder, expectedOrder);
2148 QApplication::processEvents();
2151 QTestAccessibility::clearEvents();
2154 void tst_QAccessibility::dialTest()
2158 dial.setMinimum(23);
2159 dial.setMaximum(121);
2161 QCOMPARE(dial.value(), 42);
2164 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial);
2166 QCOMPARE(interface->childCount(), 0);
2168 QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value()));
2169 QCOMPARE(interface->rect(), dial.geometry());
2171 QAccessibleValueInterface *valueIface = interface->valueInterface();
2172 QVERIFY(valueIface != 0);
2173 QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum());
2174 QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum());
2175 QCOMPARE(valueIface->currentValue().toInt(), 42);
2177 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2179 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2181 QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2182 valueIface->setCurrentValue(77);
2183 QCOMPARE(77, dial.value());
2185 QTestAccessibility::clearEvents();
2188 void tst_QAccessibility::rubberBandTest()
2190 QRubberBand rubberBand(QRubberBand::Rectangle);
2191 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand);
2193 QCOMPARE(interface->role(), QAccessible::Border);
2195 QTestAccessibility::clearEvents();
2198 void tst_QAccessibility::abstractScrollAreaTest()
2201 QAbstractScrollArea abstractScrollArea;
2203 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
2205 QVERIFY(!interface->rect().isValid());
2206 QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
2208 abstractScrollArea.resize(400, 400);
2209 abstractScrollArea.show();
2210 #if defined(Q_OS_UNIX)
2211 QCoreApplication::processEvents();
2214 const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)),
2215 abstractScrollArea.size());
2218 QCOMPARE(interface->childCount(), 1);
2219 QWidget *viewport = abstractScrollArea.viewport();
2221 QVERIFY(verifyChild(viewport, interface, 1, globalGeometry));
2223 // Horizontal scrollBar.
2224 abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2225 QCOMPARE(interface->childCount(), 2);
2226 QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar();
2227 QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget();
2228 QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry));
2230 // Horizontal scrollBar widgets.
2231 QLabel *secondLeftLabel = new QLabel(QLatin1String("L2"));
2232 abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft);
2233 QCOMPARE(interface->childCount(), 2);
2235 QLabel *firstLeftLabel = new QLabel(QLatin1String("L1"));
2236 abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft);
2237 QCOMPARE(interface->childCount(), 2);
2239 QLabel *secondRightLabel = new QLabel(QLatin1String("R2"));
2240 abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight);
2241 QCOMPARE(interface->childCount(), 2);
2243 QLabel *firstRightLabel = new QLabel(QLatin1String("R1"));
2244 abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight);
2245 QCOMPARE(interface->childCount(), 2);
2247 // Vertical scrollBar.
2248 abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2249 QCOMPARE(interface->childCount(), 3);
2250 QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar();
2251 QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget();
2252 QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry));
2254 // Vertical scrollBar widgets.
2255 QLabel *secondTopLabel = new QLabel(QLatin1String("T2"));
2256 abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop);
2257 QCOMPARE(interface->childCount(), 3);
2259 QLabel *firstTopLabel = new QLabel(QLatin1String("T1"));
2260 abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop);
2261 QCOMPARE(interface->childCount(), 3);
2263 QLabel *secondBottomLabel = new QLabel(QLatin1String("B2"));
2264 abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom);
2265 QCOMPARE(interface->childCount(), 3);
2267 QLabel *firstBottomLabel = new QLabel(QLatin1String("B1"));
2268 abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom);
2269 QCOMPARE(interface->childCount(), 3);
2272 abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C")));
2273 QCOMPARE(interface->childCount(), 4);
2274 QWidget *cornerWidget = abstractScrollArea.cornerWidget();
2275 QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry));
2278 QAccessibleInterface *target = 0;
2280 // viewport -> Up -> NOTHING
2281 const int viewportIndex = indexOfChild(interface, viewport);
2282 QVERIFY(viewportIndex != -1);
2283 QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1);
2286 // viewport -> Left -> NOTHING
2287 QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1);
2290 // viewport -> Down -> horizontalScrollBarContainer
2291 const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer);
2292 QVERIFY(horizontalScrollBarContainerIndex != -1);
2293 QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0);
2295 QCOMPARE(target->object(), static_cast<QObject *>(horizontalScrollBarContainer));
2299 // horizontalScrollBarContainer -> Left -> NOTHING
2300 QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1);
2303 // horizontalScrollBarContainer -> Down -> NOTHING
2304 QVERIFY(horizontalScrollBarContainerIndex != -1);
2305 QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1);
2308 // horizontalScrollBarContainer -> Right -> cornerWidget
2309 const int cornerWidgetIndex = indexOfChild(interface, cornerWidget);
2310 QVERIFY(cornerWidgetIndex != -1);
2311 QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0);
2313 QCOMPARE(target->object(), static_cast<QObject *>(cornerWidget));
2317 // cornerWidget -> Down -> NOTHING
2318 QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1);
2321 // cornerWidget -> Right -> NOTHING
2322 QVERIFY(cornerWidgetIndex != -1);
2323 QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1);
2326 // cornerWidget -> Up -> verticalScrollBarContainer
2327 const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer);
2328 QVERIFY(verticalScrollBarContainerIndex != -1);
2329 QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0);
2331 QCOMPARE(target->object(), static_cast<QObject *>(verticalScrollBarContainer));
2335 // verticalScrollBarContainer -> Right -> NOTHING
2336 QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1);
2339 // verticalScrollBarContainer -> Up -> NOTHING
2340 QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1);
2343 // verticalScrollBarContainer -> Left -> viewport
2344 QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0);
2346 QCOMPARE(target->object(), static_cast<QObject *>(viewport));
2350 QCOMPARE(verifyHierarchy(interface), 0);
2355 QTestAccessibility::clearEvents();
2358 void tst_QAccessibility::scrollAreaTest()
2361 QScrollArea scrollArea;
2363 #if defined(Q_OS_UNIX)
2364 QCoreApplication::processEvents();
2367 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea);
2369 QCOMPARE(interface->childCount(), 1); // The viewport.
2372 QTestAccessibility::clearEvents();
2375 void tst_QAccessibility::listTest()
2378 QListWidget *listView = new QListWidget;
2379 listView->addItem("Oslo");
2380 listView->addItem("Berlin");
2381 listView->addItem("Brisbane");
2382 listView->resize(400,400);
2384 QTest::qWait(1); // Need this for indexOfchild to work.
2385 QCoreApplication::processEvents();
2388 QAIPtr iface = QAIPtr(QAccessible::queryAccessibleInterface(listView));
2389 QCOMPARE(verifyHierarchy(iface.data()), 0);
2391 QCOMPARE((int)iface->role(), (int)QAccessible::List);
2392 QCOMPARE(iface->childCount(), 3);
2395 QAIPtr child1 = QAIPtr(iface->child(0));
2397 QCOMPARE(iface->indexOfChild(child1.data()), 1);
2398 QCOMPARE(child1->text(QAccessible::Name), QString("Oslo"));
2399 QCOMPARE(child1->role(), QAccessible::ListItem);
2401 QAIPtr child2 = QAIPtr(iface->child(1));
2403 QCOMPARE(iface->indexOfChild(child2.data()), 2);
2404 QCOMPARE(child2->text(QAccessible::Name), QString("Berlin"));
2406 QAIPtr child3 = QAIPtr(iface->child(2));
2408 QCOMPARE(iface->indexOfChild(child3.data()), 3);
2409 QCOMPARE(child3->text(QAccessible::Name), QString("Brisbane"));
2411 QTestAccessibility::clearEvents();
2414 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
2415 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
2416 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
2417 QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
2418 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
2419 QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
2421 listView->addItem("Munich");
2422 QCOMPARE(iface->childCount(), 4);
2425 QAccessibleTableInterface *table2 = iface->tableInterface();
2427 QCOMPARE(table2->columnCount(), 1);
2428 QCOMPARE(table2->rowCount(), 4);
2429 QAIPtr cell1 = QAIPtr(table2->cellAt(0,0));
2431 QCOMPARE(cell1->text(QAccessible::Name), QString("Oslo"));
2433 QAIPtr cell4 = QAIPtr(table2->cellAt(3,0));
2435 QCOMPARE(cell4->text(QAccessible::Name), QString("Munich"));
2436 QCOMPARE(cell4->role(), QAccessible::ListItem);
2438 QAccessibleTableCellInterface *cellInterface = cell4->tableCellInterface();
2439 QVERIFY(cellInterface);
2440 QCOMPARE(cellInterface->rowIndex(), 3);
2441 QCOMPARE(cellInterface->columnIndex(), 0);
2442 QCOMPARE(cellInterface->rowExtent(), 1);
2443 QCOMPARE(cellInterface->columnExtent(), 1);
2444 QCOMPARE(cellInterface->rowHeaderCells(), QList<QAccessibleInterface*>());
2445 QCOMPARE(cellInterface->columnHeaderCells(), QList<QAccessibleInterface*>());
2447 QCOMPARE(QAIPtr(cellInterface->table())->object(), listView);
2449 listView->clearSelection();
2450 QVERIFY(!(cell4->state().expandable));
2451 QVERIFY( (cell4->state().selectable));
2452 QVERIFY(!(cell4->state().selected));
2453 table2->selectRow(3);
2454 QCOMPARE(listView->selectedItems().size(), 1);
2455 QCOMPARE(listView->selectedItems().at(0)->text(), QLatin1String("Munich"));
2456 QVERIFY(cell4->state().selected);
2457 QVERIFY(cellInterface->isSelected());
2459 QVERIFY(table2->cellAt(-1, 0) == 0);
2460 QVERIFY(table2->cellAt(0, -1) == 0);
2461 QVERIFY(table2->cellAt(0, 1) == 0);
2462 QVERIFY(table2->cellAt(4, 0) == 0);
2466 QTestAccessibility::clearEvents();
2469 void tst_QAccessibility::treeTest()
2471 QTreeWidget *treeView = new QTreeWidget;
2472 treeView->setColumnCount(2);
2473 QTreeWidgetItem *header = new QTreeWidgetItem;
2474 header->setText(0, "Artist");
2475 header->setText(1, "Work");
2476 treeView->setHeaderItem(header);
2478 QTreeWidgetItem *root1 = new QTreeWidgetItem;
2479 root1->setText(0, "Spain");
2480 treeView->addTopLevelItem(root1);
2482 QTreeWidgetItem *item1 = new QTreeWidgetItem;
2483 item1->setText(0, "Picasso");
2484 item1->setText(1, "Guernica");
2485 root1->addChild(item1);
2487 QTreeWidgetItem *item2 = new QTreeWidgetItem;
2488 item2->setText(0, "Tapies");
2489 item2->setText(1, "Ambrosia");
2490 root1->addChild(item2);
2492 QTreeWidgetItem *root2 = new QTreeWidgetItem;
2493 root2->setText(0, "Austria");
2494 treeView->addTopLevelItem(root2);
2496 QTreeWidgetItem *item3 = new QTreeWidgetItem;
2497 item3->setText(0, "Klimt");
2498 item3->setText(1, "The Kiss");
2499 root2->addChild(item3);
2501 treeView->resize(400,400);
2504 QCoreApplication::processEvents();
2507 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
2508 QCOMPARE(verifyHierarchy(iface), 0);
2510 QCOMPARE((int)iface->role(), (int)QAccessible::Tree);
2511 // header and 2 rows (the others are not expanded, thus not visible)
2512 QCOMPARE(iface->childCount(), 6);
2514 QAccessibleInterface *header1 = 0;
2515 header1 = iface->child(0);
2517 QCOMPARE(iface->indexOfChild(header1), 1);
2518 QCOMPARE(header1->text(QAccessible::Name), QString("Artist"));
2519 QCOMPARE(header1->role(), QAccessible::ColumnHeader);
2522 QAccessibleInterface *child1 = 0;
2523 child1 = iface->child(2);
2525 QCOMPARE(iface->indexOfChild(child1), 3);
2526 QCOMPARE(child1->text(QAccessible::Name), QString("Spain"));
2527 QCOMPARE(child1->role(), QAccessible::TreeItem);
2528 QVERIFY(!(child1->state().expanded));
2531 QAccessibleInterface *child2 = 0;
2532 child2 = iface->child(4);
2534 QCOMPARE(iface->indexOfChild(child2), 5);
2535 QCOMPARE(child2->text(QAccessible::Name), QString("Austria"));
2538 QTestAccessibility::clearEvents();
2541 QAccessibleTableInterface *table2 = iface->tableInterface();
2543 QCOMPARE(table2->columnCount(), 2);
2544 QCOMPARE(table2->rowCount(), 2);
2545 QAccessibleInterface *cell1;
2546 QVERIFY(cell1 = table2->cellAt(0,0));
2547 QCOMPARE(cell1->text(QAccessible::Name), QString("Spain"));
2548 QAccessibleInterface *cell2;
2549 QVERIFY(cell2 = table2->cellAt(1,0));
2550 QCOMPARE(cell2->text(QAccessible::Name), QString("Austria"));
2551 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2552 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1);
2553 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2554 QVERIFY(cell2->state().expandable);
2555 QCOMPARE(iface->indexOfChild(cell2), 5);
2556 QVERIFY(!(cell2->state().expanded));
2557 QCOMPARE(table2->columnDescription(1), QString("Work"));
2561 treeView->expandAll();
2563 // Need this for indexOfchild to work.
2564 QCoreApplication::processEvents();
2567 QCOMPARE(table2->columnCount(), 2);
2568 QCOMPARE(table2->rowCount(), 5);
2569 cell1 = table2->cellAt(1,0);
2570 QCOMPARE(cell1->text(QAccessible::Name), QString("Picasso"));
2571 QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
2573 cell2 = table2->cellAt(4,0);
2574 QCOMPARE(cell2->text(QAccessible::Name), QString("Klimt"));
2575 QCOMPARE(cell2->role(), QAccessible::TreeItem);
2576 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4);
2577 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2578 QVERIFY(!(cell2->state().expandable));
2579 QCOMPARE(iface->indexOfChild(cell2), 11);
2581 QCOMPARE(table2->columnDescription(0), QString("Artist"));
2582 QCOMPARE(table2->columnDescription(1), QString("Work"));
2585 QTestAccessibility::clearEvents();
2588 void tst_QAccessibility::tableTest()
2590 QTableWidget *tableView = new QTableWidget(3, 3);
2591 tableView->setColumnCount(3);
2592 QStringList hHeader;
2593 hHeader << "h1" << "h2" << "h3";
2594 tableView->setHorizontalHeaderLabels(hHeader);
2596 QStringList vHeader;
2597 vHeader << "v1" << "v2" << "v3";
2598 tableView->setVerticalHeaderLabels(vHeader);
2600 for (int i = 0; i<9; ++i) {
2601 QTableWidgetItem *item = new QTableWidgetItem;
2602 item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
2603 tableView->setItem(i/3, i%3, item);
2606 tableView->resize(600,600);
2608 QTest::qWait(1); // Need this for indexOfchild to work.
2609 QCoreApplication::processEvents();
2612 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
2613 QCOMPARE(verifyHierarchy(iface), 0);
2615 QCOMPARE((int)iface->role(), (int)QAccessible::Table);
2616 // header and 2 rows (the others are not expanded, thus not visible)
2617 QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
2619 QAccessibleInterface *cornerButton = iface->child(0);
2620 QVERIFY(cornerButton);
2621 QCOMPARE(iface->indexOfChild(cornerButton), 1);
2622 QCOMPARE(cornerButton->role(), QAccessible::Pane);
2623 delete cornerButton;
2625 QAccessibleInterface *child1 = iface->child(2);
2627 QCOMPARE(iface->indexOfChild(child1), 3);
2628 QCOMPARE(child1->text(QAccessible::Name), QString("h2"));
2629 QCOMPARE(child1->role(), QAccessible::ColumnHeader);
2630 QVERIFY(!(child1->state().expanded));
2633 QAccessibleInterface *child2 = iface->child(10);
2635 QCOMPARE(iface->indexOfChild(child2), 11);
2636 QCOMPARE(child2->text(QAccessible::Name), QString("1.1"));
2637 QAccessibleTableCellInterface *cell2Iface = child2->tableCellInterface();
2638 QCOMPARE(cell2Iface->rowIndex(), 1);
2639 QCOMPARE(cell2Iface->columnIndex(), 1);
2642 QAccessibleInterface *child3 = iface->child(11);
2643 QCOMPARE(iface->indexOfChild(child3), 12);
2644 QCOMPARE(child3->text(QAccessible::Name), QString("1.2"));
2647 QTestAccessibility::clearEvents();
2650 QAccessibleTableInterface *table2 = iface->tableInterface();
2652 QCOMPARE(table2->columnCount(), 3);
2653 QCOMPARE(table2->rowCount(), 3);
2654 QAccessibleInterface *cell1;
2655 QVERIFY(cell1 = table2->cellAt(0,0));
2656 QCOMPARE(cell1->text(QAccessible::Name), QString("0.0"));
2657 QCOMPARE(iface->indexOfChild(cell1), 6);
2659 QAccessibleInterface *cell2;
2660 QVERIFY(cell2 = table2->cellAt(0,1));
2661 QCOMPARE(cell2->text(QAccessible::Name), QString("0.1"));
2662 QCOMPARE(cell2->role(), QAccessible::Cell);
2663 QCOMPARE(cell2->tableCellInterface()->rowIndex(), 0);
2664 QCOMPARE(cell2->tableCellInterface()->columnIndex(), 1);
2665 QCOMPARE(iface->indexOfChild(cell2), 7);
2668 QAccessibleInterface *cell3;
2669 QVERIFY(cell3 = table2->cellAt(1,2));
2670 QCOMPARE(cell3->text(QAccessible::Name), QString("1.2"));
2671 QCOMPARE(cell3->role(), QAccessible::Cell);
2672 QCOMPARE(cell3->tableCellInterface()->rowIndex(), 1);
2673 QCOMPARE(cell3->tableCellInterface()->columnIndex(), 2);
2674 QCOMPARE(iface->indexOfChild(cell3), 12);
2677 QCOMPARE(table2->columnDescription(0), QString("h1"));
2678 QCOMPARE(table2->columnDescription(1), QString("h2"));
2679 QCOMPARE(table2->columnDescription(2), QString("h3"));
2680 QCOMPARE(table2->rowDescription(0), QString("v1"));
2681 QCOMPARE(table2->rowDescription(1), QString("v2"));
2682 QCOMPARE(table2->rowDescription(2), QString("v3"));
2688 QTestAccessibility::clearEvents();
2691 void tst_QAccessibility::calendarWidgetTest()
2693 #ifndef QT_NO_CALENDARWIDGET
2695 QCalendarWidget calendarWidget;
2697 QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget);
2699 QCOMPARE(interface->role(), QAccessible::Table);
2700 QVERIFY(!interface->rect().isValid());
2701 QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
2703 calendarWidget.resize(400, 300);
2704 calendarWidget.show();
2705 #if defined(Q_OS_UNIX)
2706 QCoreApplication::processEvents();
2710 // 1 = navigationBar, 2 = view.
2711 QCOMPARE(interface->childCount(), 2);
2713 const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)),
2714 calendarWidget.size());
2715 QCOMPARE(interface->rect(), globalGeometry);
2717 QWidget *navigationBar = 0;
2718 foreach (QObject *child, calendarWidget.children()) {
2719 if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) {
2720 navigationBar = static_cast<QWidget *>(child);
2724 QVERIFY(navigationBar);
2725 QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry));
2727 QAbstractItemView *calendarView = 0;
2728 foreach (QObject *child, calendarWidget.children()) {
2729 if (child->objectName() == QLatin1String("qt_calendar_calendarview")) {
2730 calendarView = static_cast<QAbstractItemView *>(child);
2734 QVERIFY(calendarView);
2735 QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry));
2737 // Hide navigation bar.
2738 calendarWidget.setNavigationBarVisible(false);
2739 QCOMPARE(interface->childCount(), 1);
2740 QVERIFY(!navigationBar->isVisible());
2742 QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry));
2744 // Show navigation bar.
2745 calendarWidget.setNavigationBarVisible(true);
2746 QCOMPARE(interface->childCount(), 2);
2747 QVERIFY(navigationBar->isVisible());
2749 // Navigate to the navigation bar via Child.
2750 QAccessibleInterface *navigationBarInterface = interface->child(0);
2751 QVERIFY(navigationBarInterface);
2752 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2753 delete navigationBarInterface;
2754 navigationBarInterface = 0;
2756 // Navigate to the view via Child.
2757 QAccessibleInterface *calendarViewInterface = interface->child(1);
2758 QVERIFY(calendarViewInterface);
2759 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2760 delete calendarViewInterface;
2761 calendarViewInterface = 0;
2763 QVERIFY(!interface->child(-1));
2765 // Navigate from navigation bar -> view (Down).
2766 QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0);
2767 QVERIFY(calendarViewInterface);
2768 QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2769 delete calendarViewInterface;
2770 calendarViewInterface = 0;
2772 // Navigate from view -> navigation bar (Up).
2773 QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0);
2774 QVERIFY(navigationBarInterface);
2775 QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2776 delete navigationBarInterface;
2777 navigationBarInterface = 0;
2780 QTestAccessibility::clearEvents();
2781 #endif // QT_NO_CALENDARWIDGET
2784 void tst_QAccessibility::dockWidgetTest()
2786 #ifndef QT_NO_DOCKWIDGET
2787 // Set up a proper main window with two dock widgets
2788 QMainWindow *mw = new QMainWindow();
2789 QFrame *central = new QFrame(mw);
2790 mw->setCentralWidget(central);
2791 QMenuBar *mb = new QMenuBar(mw);
2792 mb->addAction(tr("&File"));
2795 QDockWidget *dock1 = new QDockWidget(mw);
2796 mw->addDockWidget(Qt::LeftDockWidgetArea, dock1);
2797 QPushButton *pb1 = new QPushButton(tr("Push me"), dock1);
2798 dock1->setWidget(pb1);
2800 QDockWidget *dock2 = new QDockWidget(mw);
2801 mw->addDockWidget(Qt::BottomDockWidgetArea, dock2);
2802 QPushButton *pb2 = new QPushButton(tr("Push me"), dock2);
2803 dock2->setWidget(pb2);
2805 mw->resize(600,400);
2807 #if defined(Q_OS_UNIX)
2808 QCoreApplication::processEvents();
2812 QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw);
2813 // 4 children: menu bar, dock1, dock2, and central widget
2814 QCOMPARE(accMainWindow->childCount(), 4);
2815 QAccessibleInterface *accDock1 = 0;
2816 for (int i = 0; i < 4; ++i) {
2817 accDock1 = accMainWindow->child(i);
2818 if (accMainWindow->role() == QAccessible::Window) {
2819 if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) {
2827 QCOMPARE(accDock1->role(), QAccessible::Window);
2829 QAccessibleInterface *dock1TitleBar = accDock1->child(0);
2830 QCOMPARE(dock1TitleBar->role(), QAccessible::TitleBar);
2831 QVERIFY(accDock1->rect().contains(dock1TitleBar->rect()));
2832 delete dock1TitleBar;
2834 QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
2835 globalPos.rx()+=5; //### query style
2837 QAccessibleInterface *childAt = accDock1->childAt(globalPos.x(), globalPos.y()); //###
2838 QCOMPARE(childAt->role(), QAccessible::TitleBar);
2839 int index = accDock1->indexOfChild(childAt);
2841 QAccessibleInterface *accTitleBar = accDock1->child(index - 1);
2843 QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
2844 QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);
2845 QAccessibleInterface *acc;
2846 acc = accTitleBar->parent();
2848 QCOMPARE(acc->role(), QAccessible::Window);
2858 QTestAccessibility::clearEvents();
2859 #endif // QT_NO_DOCKWIDGET
2862 void tst_QAccessibility::comboBoxTest()
2864 #if defined(Q_OS_WINCE)
2865 if (!IsValidCEPlatform())
2866 QSKIP("Test skipped on Windows Mobile test hardware");
2868 { // not editable combobox
2870 combo.addItems(QStringList() << "one" << "two" << "three");
2872 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
2873 QCOMPARE(verifyHierarchy(iface), 0);
2875 QCOMPARE(iface->role(), QAccessible::ComboBox);
2876 QCOMPARE(iface->childCount(), 1);
2879 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one"));
2881 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one"));
2882 combo.setCurrentIndex(2);
2884 QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three"));
2886 QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three"));
2888 QAccessibleInterface *listIface = iface->child(0);
2889 QCOMPARE(listIface->role(), QAccessible::List);
2890 QCOMPARE(listIface->childCount(), 3);
2892 QVERIFY(!combo.view()->isVisible());
2893 QVERIFY(iface->actionInterface());
2894 QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
2895 iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
2896 QVERIFY(combo.view()->isVisible());
2901 { // editable combobox
2902 QComboBox editableCombo;
2903 editableCombo.show();
2904 editableCombo.setEditable(true);
2905 editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
2907 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo);
2908 QCOMPARE(verifyHierarchy(iface), 0);
2910 QCOMPARE(iface->role(), QAccessible::ComboBox);
2911 QCOMPARE(iface->childCount(), 2);
2913 QAccessibleInterface *listIface = iface->child(0);
2914 QCOMPARE(listIface->role(), QAccessible::List);
2915 QAccessibleInterface *editIface = iface->child(1);
2916 QCOMPARE(editIface->role(), QAccessible::EditableText);
2923 QTestAccessibility::clearEvents();
2926 void tst_QAccessibility::labelTest()
2928 QString text = "Hello World";
2929 QLabel *label = new QLabel(text);
2932 #if defined(Q_OS_UNIX)
2933 QCoreApplication::processEvents();
2937 QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label);
2940 QCOMPARE(acc_label->text(QAccessible::Name), text);
2944 QTestAccessibility::clearEvents();
2946 QPixmap testPixmap(50, 50);
2950 imageLabel.setPixmap(testPixmap);
2951 imageLabel.setToolTip("Test Description");
2953 acc_label = QAccessible::queryAccessibleInterface(&imageLabel);
2956 QAccessibleImageInterface *imageInterface = acc_label->imageInterface();
2957 QVERIFY(imageInterface);
2959 QCOMPARE(imageInterface->imageSize(), testPixmap.size());
2960 QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
2961 QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
2965 QTestAccessibility::clearEvents();
2968 void tst_QAccessibility::accelerators()
2970 QWidget *window = new QWidget;
2971 QHBoxLayout *lay = new QHBoxLayout(window);
2972 QLabel *label = new QLabel(tr("&Line edit"), window);
2973 QLineEdit *le = new QLineEdit(window);
2974 lay->addWidget(label);
2976 label->setBuddy(le);
2980 QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
2981 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
2982 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
2983 label->setText(tr("Q &"));
2984 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
2985 label->setText(tr("Q &&"));
2986 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
2987 label->setText(tr("Q && A"));
2988 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
2989 label->setText(tr("Q &&&A"));
2990 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
2991 label->setText(tr("Q &&A"));
2992 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
2994 #if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC)
2995 QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'");
2997 label->setText(tr("Q &A&B"));
2998 QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3000 #if defined(Q_OS_UNIX)
3001 QCoreApplication::processEvents();
3005 QTestAccessibility::clearEvents();
3008 QTEST_MAIN(tst_QAccessibility)
3009 #include "tst_qaccessibility.moc"