Merge remote-tracking branch 'gerrit/master' into containers
[profile/ivi/qtbase.git] / tests / auto / other / qaccessibility / tst_qaccessibility.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44 #include <QtGui>
45 #include <QtWidgets>
46 #include <math.h>
47
48 #if defined(Q_OS_WIN) && defined(interface)
49 #   undef interface
50 #endif
51
52
53 #include "QtTest/qtestaccessible.h"
54
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")))
63             return false;
64     }
65     return true;
66 }
67 #endif
68
69 static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
70                                int index, const QRect &domain)
71 {
72     if (!child) {
73         qWarning("tst_QAccessibility::verifyChild: null pointer to child.");
74         return false;
75     }
76
77     if (!interface) {
78         qWarning("tst_QAccessibility::verifyChild: null pointer to interface.");
79         return false;
80     }
81
82     // Verify that we get a valid QAccessibleInterface for the child.
83     QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(child);
84     if (!childInterface) {
85         qWarning("tst_QAccessibility::verifyChild: Failed to retrieve interface for child.");
86         return false;
87     }
88
89     // QAccessibleInterface::indexOfChild():
90     // Verify that indexOfChild() returns an index equal to the index passed in
91     int indexFromIndexOfChild = interface->indexOfChild(childInterface);
92     delete childInterface;
93     if (indexFromIndexOfChild != index) {
94         qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
95         qWarning() << "Expected:" << index;
96         qWarning() << "Actual:  " << indexFromIndexOfChild;
97         return false;
98     }
99
100     // Navigate to child, compare its object and role with the interface from queryAccessibleInterface(child).
101     QAccessibleInterface *navigatedChildInterface = interface->child(index - 1);
102     if (navigatedChildInterface == 0)
103         return false;
104
105     const QRect rectFromInterface = navigatedChildInterface->rect();
106     delete navigatedChildInterface;
107
108     // QAccessibleInterface::childAt():
109     // Calculate global child position and check that the interface
110     // returns the correct index for that position.
111     QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
112     int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y());
113     if (indexFromChildAt != index) {
114         qWarning("tst_QAccessibility::verifyChild (childAt()):");
115         qWarning() << "Expected:" << index;
116         qWarning() << "Actual:  " << indexFromChildAt;
117         return false;
118     }
119
120     // QAccessibleInterface::rect():
121     // Calculate global child geometry and check that the interface
122     // returns a QRect which is equal to the calculated QRect.
123     const QRect expectedGlobalRect = QRect(globalChildPos, child->size());
124     if (expectedGlobalRect != rectFromInterface) {
125         qWarning("tst_QAccessibility::verifyChild (rect()):");
126         qWarning() << "Expected:" << expectedGlobalRect;
127         qWarning() << "Actual:  " << rectFromInterface;
128         return false;
129     }
130
131     // Verify that the child is within its domain.
132     if (!domain.contains(rectFromInterface)) {
133         qWarning("tst_QAccessibility::verifyChild: Child is not within its domain.");
134         return false;
135     }
136
137     return true;
138 }
139
140 static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget)
141 {
142     if (!parentInterface || !childWidget)
143         return -1;
144     QAccessibleInterface *childInterface = QAccessible::queryAccessibleInterface(childWidget);
145     if (!childInterface)
146         return -1;
147     int index = parentInterface->indexOfChild(childInterface);
148     delete childInterface;
149     return index;
150 }
151
152 #define EXPECT(cond) \
153     do { \
154         if (!errorAt && !(cond)) { \
155             errorAt = __LINE__; \
156             qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
157         } \
158     } while (0)
159
160 static int verifyHierarchy(QAccessibleInterface *iface)
161 {
162     int errorAt = 0;
163     static int treelevel = 0;   // for error diagnostics
164     QAccessibleInterface *middleChild, *if2;
165     middleChild = 0;
166     ++treelevel;
167     int middle = iface->childCount()/2 + 1;
168     if (iface->childCount() >= 2) {
169         middleChild = iface->child(middle - 1);
170     }
171     for (int i = 0; i < iface->childCount() && !errorAt; ++i) {
172         if2 = iface->child(i);
173         EXPECT(if2 != 0);
174         // navigate Ancestor...
175         QAccessibleInterface *parent = if2->parent();
176         EXPECT(iface->object() == parent->object());
177         delete parent;
178
179             // navigate Sibling...
180 //            if (middleChild) {
181 //                entry = if2->navigate(QAccessible::Sibling, middle, &if3);
182 //                EXPECT(entry == 0 && if3->object() == middleChild->object());
183 //                if (entry == 0)
184 //                    delete if3;
185 //                EXPECT(iface->indexOfChild(middleChild) == middle);
186 //            }
187
188         // verify children...
189         if (!errorAt)
190             errorAt = verifyHierarchy(if2);
191         delete if2;
192     }
193     delete middleChild;
194
195     --treelevel;
196     return errorAt;
197 }
198
199 QRect childRect(QAccessibleInterface *iface, int index = 0)
200 {
201     QAccessibleInterface *child = iface->child(index);
202     QRect rect = child->rect();
203     delete child;
204     return rect;
205 }
206
207 class tst_QAccessibility : public QObject
208 {
209     Q_OBJECT
210 public:
211     tst_QAccessibility();
212     virtual ~tst_QAccessibility();
213
214 public slots:
215     void initTestCase();
216     void cleanupTestCase();
217     void init();
218     void cleanup();
219 private slots:
220     void eventTest();
221     void customWidget();
222     void deletedWidget();
223
224     void navigateGeometric();
225     void navigateHierarchy();
226     void sliderTest();
227     void navigateCovered();
228     void textAttributes();
229     void hideShowTest();
230
231     void actionTest();
232
233     void applicationTest();
234     void mainWindowTest();
235     void buttonTest();
236     void scrollBarTest();
237     void tabTest();
238     void tabWidgetTest();
239     void menuTest();
240     void spinBoxTest();
241     void doubleSpinBoxTest();
242     void textEditTest();
243     void textBrowserTest();
244     void mdiAreaTest();
245     void mdiSubWindowTest();
246     void lineEditTest();
247     void workspaceTest();
248     void dialogButtonBoxTest();
249     void dialTest();
250     void rubberBandTest();
251     void abstractScrollAreaTest();
252     void scrollAreaTest();
253
254     void listTest();
255     void treeTest();
256     void tableTest();
257
258     void calendarWidgetTest();
259     void dockWidgetTest();
260     void comboBoxTest();
261     void accessibleName();
262     void labelTest();
263     void accelerators();
264
265 protected slots:
266     void onClicked();
267 private:
268     int click_count;
269 };
270
271 const double Q_PI = 3.14159265358979323846;
272
273 QString eventName(const int ev)
274 {
275     switch(ev) {
276     case 0x0001: return "SoundPlayed";
277     case 0x0002: return "Alert";
278     case 0x0003: return "ForegroundChanged";
279     case 0x0004: return "MenuStart";
280     case 0x0005: return "MenuEnd";
281     case 0x0006: return "PopupMenuStart";
282     case 0x0007: return "PopupMenuEnd";
283     case 0x000C: return "ContextHelpStart";
284     case 0x000D: return "ContextHelpEnd";
285     case 0x000E: return "DragDropStart";
286     case 0x000F: return "DragDropEnd";
287     case 0x0010: return "DialogStart";
288     case 0x0011: return "DialogEnd";
289     case 0x0012: return "ScrollingStart";
290     case 0x0013: return "ScrollingEnd";
291     case 0x0018: return "MenuCommand";
292
293     case 0x0116: return "TableModelChanged";
294     case 0x011B: return "TextCaretMoved";
295
296     case 0x8000: return "ObjectCreated";
297     case 0x8001: return "ObjectDestroyed";
298     case 0x8002: return "ObjectShow";
299     case 0x8003: return "ObjectHide";
300     case 0x8004: return "ObjectReorder";
301     case 0x8005: return "Focus";
302     case 0x8006: return "Selection";
303     case 0x8007: return "SelectionAdd";
304     case 0x8008: return "SelectionRemove";
305     case 0x8009: return "SelectionWithin";
306     case 0x800A: return "StateChanged";
307     case 0x800B: return "LocationChanged";
308     case 0x800C: return "NameChanged";
309     case 0x800D: return "DescriptionChanged";
310     case 0x800E: return "ValueChanged";
311     case 0x800F: return "ParentChanged";
312     case 0x80A0: return "HelpChanged";
313     case 0x80B0: return "DefaultActionChanged";
314     case 0x80C0: return "AcceleratorChanged";
315     default: return "Unknown Event";
316     }
317 }
318
319 QAccessible::State state(QWidget * const widget)
320 {
321     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
322     if (!iface)
323         qWarning() << "Cannot get QAccessibleInterface for widget";
324     QAccessible::State state = (iface ? iface->state() : static_cast<QAccessible::State>(0));
325     delete iface;
326     return state;
327 }
328
329 class QtTestAccessibleWidget: public QWidget
330 {
331     Q_OBJECT
332 public:
333     QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent)
334     {
335         setObjectName(name);
336         QPalette pal;
337         pal.setColor(backgroundRole(), Qt::black);//black is beautiful
338         setPalette(pal);
339         setFixedSize(5, 5);
340     }
341 };
342
343 class QtTestAccessibleWidgetIface: public QAccessibleWidget
344 {
345 public:
346     QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {}
347     QString text(QAccessible::Text t) const
348     {
349         if (t == QAccessible::Help)
350             return QString::fromLatin1("Help yourself");
351         return QAccessibleWidget::text(t);
352     }
353     static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o)
354     {
355         if (key == "QtTestAccessibleWidget")
356             return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o));
357         return 0;
358     }
359 };
360
361 tst_QAccessibility::tst_QAccessibility()
362 {
363     click_count = 0;
364 }
365
366 tst_QAccessibility::~tst_QAccessibility()
367 {
368 }
369
370 void tst_QAccessibility::onClicked()
371 {
372     click_count++;
373 }
374
375 void tst_QAccessibility::initTestCase()
376 {
377     QTestAccessibility::initialize();
378     QAccessible::installFactory(QtTestAccessibleWidgetIface::ifaceFactory);
379 }
380
381 void tst_QAccessibility::cleanupTestCase()
382 {
383     QTestAccessibility::cleanup();
384 }
385
386 void tst_QAccessibility::init()
387 {
388     QTestAccessibility::clearEvents();
389 }
390
391 void tst_QAccessibility::cleanup()
392 {
393     const EventList list = QTestAccessibility::events();
394     if (!list.isEmpty()) {
395         qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
396                  QString(QTest::currentTestFunction()).toAscii().constData());
397         for (int i = 0; i < list.count(); ++i)
398             qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
399                      eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
400     }
401     QTestAccessibility::clearEvents();
402 }
403
404 void tst_QAccessibility::eventTest()
405 {
406     QPushButton* button = new QPushButton(0);
407     button->setObjectName(QString("Olaf"));
408
409     button->show();
410     QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
411     button->setFocus(Qt::MouseFocusReason);
412     QTestAccessibility::clearEvents();
413     QTest::mouseClick(button, Qt::LeftButton, 0);
414     QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
415     QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
416
417     button->setAccessibleName("Olaf the second");
418     QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
419     button->setAccessibleDescription("This is a button labeled Olaf");
420     QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
421
422     button->hide();
423     QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
424
425     delete button;
426 }
427
428 void tst_QAccessibility::customWidget()
429 {
430     QtTestAccessibleWidget* widget = new QtTestAccessibleWidget(0, "Heinz");
431
432     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
433     QVERIFY(iface != 0);
434     QVERIFY(iface->isValid());
435     QCOMPARE(iface->object(), (QObject*)widget);
436     QCOMPARE(iface->object()->objectName(), QString("Heinz"));
437     QCOMPARE(iface->text(QAccessible::Help), QString("Help yourself"));
438
439     delete iface;
440     delete widget;
441 }
442
443 void tst_QAccessibility::deletedWidget()
444 {
445     QtTestAccessibleWidget *widget = new QtTestAccessibleWidget(0, "Ralf");
446     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
447     QVERIFY(iface != 0);
448     QVERIFY(iface->isValid());
449     QCOMPARE(iface->object(), (QObject*)widget);
450
451     delete widget;
452     widget = 0;
453     QVERIFY(!iface->isValid());
454     delete iface;
455 }
456
457 void tst_QAccessibility::navigateGeometric()
458 {
459     {
460     static const int skip = 20; //speed the test up significantly
461     static const double step = Q_PI / 180;
462     QWidget *w = new QWidget(0);
463     w->setObjectName(QString("Josef"));
464     w->setFixedSize(400, 400);
465
466     // center widget
467     QtTestAccessibleWidget *center = new QtTestAccessibleWidget(w, "Sol");
468     center->move(200, 200);
469
470     // arrange 360 widgets around it in a circle
471     QtTestAccessibleWidget *aw = 0;
472     for (int i = 0; i < 360; i += skip) {
473         aw = new QtTestAccessibleWidget(w, QString::number(i).toLatin1());
474         aw->move( int(200.0 + 100.0 * sin(step * (double)i)), int(200.0 + 100.0 * cos(step * (double)i)) );
475     }
476
477     aw = new QtTestAccessibleWidget(w, "Earth");
478     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(center);
479     QAccessibleInterface *target = 0;
480     QVERIFY(iface != 0);
481     QVERIFY(iface->isValid());
482
483     w->show();
484     QCoreApplication::processEvents();
485     QTest::qWait(100);
486
487     // let one widget rotate around center
488     for (int i = 0; i < 360; i+=skip) {
489         aw->move( int(200.0 + 75.0 * sin(step * (double)i)), int(200.0 + 75.0 * cos(step * (double)i)) );
490
491         if (i < 45 || i > 315) {
492             QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
493         } else if ( i < 135 ) {
494             QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
495         } else if ( i < 225 ) {
496             QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
497         } else {
498             QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
499         }
500
501         QVERIFY(target);
502         QVERIFY(target->isValid());
503         QVERIFY(target->object());
504         QCOMPARE(target->object()->objectName(), aw->objectName());
505         delete target; target = 0;
506     }
507
508     // test invisible widget
509     target = QAccessible::queryAccessibleInterface(aw);
510     QVERIFY(!(target->state() & QAccessible::Invisible));
511     aw->hide();
512     QVERIFY(target->state() & QAccessible::Invisible);
513     delete target; target = 0;
514
515     aw->move(center->x() + 10, center->y());
516     QCOMPARE(iface->navigate(QAccessible::Right, 0, &target), 0);
517     QVERIFY(target);
518     QVERIFY(target->isValid());
519     QVERIFY(target->object());
520     QVERIFY(QString(target->object()->objectName()) != "Earth");
521     delete target; target = 0;
522
523     aw->move(center->x() - 10, center->y());
524     QCOMPARE(iface->navigate(QAccessible::Left, 0, &target), 0);
525     QVERIFY(target);
526     QVERIFY(target->isValid());
527     QVERIFY(target->object());
528     QVERIFY(QString(target->object()->objectName()) != "Earth");
529     delete target; target = 0;
530
531     aw->move(center->x(), center->y() + 10);
532     QCOMPARE(iface->navigate(QAccessible::Down, 0, &target), 0);
533     QVERIFY(target);
534     QVERIFY(target->isValid());
535     QVERIFY(target->object());
536     QVERIFY(QString(target->object()->objectName()) != "Earth");
537     delete target; target = 0;
538
539     aw->move(center->x(), center->y() - 10);
540     QCOMPARE(iface->navigate(QAccessible::Up, 0, &target), 0);
541     QVERIFY(target);
542     QVERIFY(target->isValid());
543     QVERIFY(target->object());
544     QVERIFY(QString(target->object()->objectName()) != "Earth");
545     delete target; target = 0;
546
547     delete iface;
548     delete w;
549     }
550     QTestAccessibility::clearEvents();
551 }
552
553 void tst_QAccessibility::sliderTest()
554 {
555     {
556     QSlider *slider = new QSlider(0);
557     slider->setObjectName(QString("Slidy"));
558     slider->show();
559     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(slider);
560     QVERIFY(iface != 0);
561     QVERIFY(iface->isValid());
562
563     QCOMPARE(iface->childCount(), 0);
564     QCOMPARE(iface->role(), QAccessible::Slider);
565
566     QAccessibleValueInterface *valueIface = iface->valueInterface();
567     QVERIFY(valueIface != 0);
568     QCOMPARE(valueIface->minimumValue().toInt(), slider->minimum());
569     QCOMPARE(valueIface->maximumValue().toInt(), slider->maximum());
570     slider->setValue(50);
571     QCOMPARE(valueIface->currentValue().toInt(), slider->value());
572     slider->setValue(0);
573     QCOMPARE(valueIface->currentValue().toInt(), slider->value());
574     slider->setValue(100);
575     QCOMPARE(valueIface->currentValue().toInt(), slider->value());
576     valueIface->setCurrentValue(77);
577     QCOMPARE(77, slider->value());
578
579     delete iface;
580     delete slider;
581     }
582     QTestAccessibility::clearEvents();
583 }
584
585 void tst_QAccessibility::navigateCovered()
586 {
587     {
588     QWidget *w = new QWidget(0);
589     w->setObjectName(QString("Harry"));
590     QWidget *w1 = new QWidget(w);
591     w1->setObjectName(QString("1"));
592     QWidget *w2 = new QWidget(w);
593     w2->setObjectName(QString("2"));
594     w->show();
595 #if defined(Q_OS_UNIX)
596     QCoreApplication::processEvents();
597     QTest::qWait(100);
598 #endif
599
600     w->setFixedSize(6, 6);
601     w1->setFixedSize(5, 5);
602     w2->setFixedSize(5, 5);
603     w2->move(0, 0);
604     w1->raise();
605
606     QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(w1);
607     QVERIFY(iface1 != 0);
608     QVERIFY(iface1->isValid());
609     QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(w2);
610     QVERIFY(iface2 != 0);
611     QVERIFY(iface2->isValid());
612     QAccessibleInterface *iface3 = 0;
613
614     QCOMPARE(iface1->navigate(QAccessible::Covers, -42, &iface3), -1);
615     QVERIFY(iface3 == 0);
616     QCOMPARE(iface1->navigate(QAccessible::Covers, 0, &iface3), -1);
617     QVERIFY(iface3 == 0);
618     QCOMPARE(iface1->navigate(QAccessible::Covers, 2, &iface3), -1);
619     QVERIFY(iface3 == 0);
620
621     for (int loop = 0; loop < 2; ++loop) {
622         for (int x = 0; x < w->width(); ++x) {
623             for (int y = 0; y < w->height(); ++y) {
624                 w1->move(x, y);
625                 if (w1->geometry().intersects(w2->geometry())) {
626                     QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
627                     QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
628                     QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), 0);
629                     QVERIFY(iface3 != 0);
630                     QVERIFY(iface3->isValid());
631                     QCOMPARE(iface3->object(), iface2->object());
632                     delete iface3; iface3 = 0;
633                     QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), 0);
634                     QVERIFY(iface3 != 0);
635                     QVERIFY(iface3->isValid());
636                     QCOMPARE(iface3->object(), iface1->object());
637                     delete iface3; iface3 = 0;
638                 } else {
639                     QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
640                     QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
641                     QCOMPARE(iface1->navigate(QAccessible::Covered, 1, &iface3), -1);
642                     QVERIFY(iface3 == 0);
643                     QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
644                     QVERIFY(iface3 == 0);
645                     QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
646                     QVERIFY(iface3 == 0);
647                     QCOMPARE(iface2->navigate(QAccessible::Covers, 1, &iface3), -1);
648                     QVERIFY(iface3 == 0);
649                 }
650             }
651         }
652         if (!loop) {
653             // switch children for second loop
654             w2->raise();
655             QAccessibleInterface *temp = iface1;
656             iface1 = iface2;
657             iface2 = temp;
658         }
659     }
660     delete iface1; iface1 = 0;
661     delete iface2; iface2 = 0;
662     iface1 = QAccessible::queryAccessibleInterface(w1);
663     QVERIFY(iface1 != 0);
664     QVERIFY(iface1->isValid());
665     iface2 = QAccessible::queryAccessibleInterface(w2);
666     QVERIFY(iface2 != 0);
667     QVERIFY(iface2->isValid());
668
669     w1->move(0,0);
670     w2->move(0,0);
671     w1->raise();
672     QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
673     QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
674     QVERIFY(!(iface1->state() & QAccessible::Invisible));
675     w1->hide();
676     QVERIFY(iface1->state() & QAccessible::Invisible);
677     QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
678     QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
679     QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
680     QVERIFY(iface3 == 0);
681     QCOMPARE(iface1->navigate(QAccessible::Covers, 1, &iface3), -1);
682     QVERIFY(iface3 == 0);
683
684     delete iface1; iface1 = 0;
685     delete iface2; iface2 = 0;
686     delete w;
687     }
688     QTestAccessibility::clearEvents();
689 }
690
691 void tst_QAccessibility::navigateHierarchy()
692 {
693     {
694     QWidget *w = new QWidget(0);
695     w->setObjectName(QString("Hans"));
696     w->show();
697     QWidget *w1 = new QWidget(w);
698     w1->setObjectName(QString("1"));
699     w1->show();
700     QWidget *w2 = new QWidget(w);
701     w2->setObjectName(QString("2"));
702     w2->show();
703     QWidget *w3 = new QWidget(w);
704     w3->setObjectName(QString("3"));
705     w3->show();
706     QWidget *w31 = new QWidget(w3);
707     w31->setObjectName(QString("31"));
708     w31->show();
709
710     QAccessibleInterface *target = 0;
711     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w);
712     QVERIFY(iface != 0);
713     QVERIFY(iface->isValid());
714
715     QCOMPARE(iface->navigate(QAccessible::Sibling, -42, &target), -1);
716     QVERIFY(target == 0);
717     QCOMPARE(iface->navigate(QAccessible::Sibling, 42, &target), -1);
718     QVERIFY(target == 0);
719
720     target = iface->child(14);
721     QVERIFY(target == 0);
722     target = iface->child(-1);
723     QVERIFY(target == 0);
724     target = iface->child(0);
725     QAccessibleInterface *interfaceW1 = iface->child(0);
726     QVERIFY(target);
727     QVERIFY(target->isValid());
728     QCOMPARE(target->object(), (QObject*)w1);
729     QVERIFY(interfaceW1 != 0);
730     QVERIFY(interfaceW1->isValid());
731     QCOMPARE(interfaceW1->object(), (QObject*)w1);
732     delete interfaceW1;
733     delete iface; iface = 0;
734
735     QCOMPARE(target->navigate(QAccessible::Sibling, 0, &iface), -1);
736     QVERIFY(iface == 0);
737     QCOMPARE(target->navigate(QAccessible::Sibling, 42, &iface), -1);
738     QVERIFY(iface == 0);
739     QCOMPARE(target->navigate(QAccessible::Sibling, -42, &iface), -1);
740     QVERIFY(iface == 0);
741     QCOMPARE(target->navigate(QAccessible::Sibling, 2, &iface), 0);
742     QVERIFY(iface != 0);
743     QVERIFY(iface->isValid());
744     QCOMPARE(iface->object(), (QObject*)w2);
745     delete target; target = 0;
746     QCOMPARE(iface->navigate(QAccessible::Sibling, 3, &target), 0);
747     QVERIFY(target != 0);
748     QVERIFY(target->isValid());
749     QCOMPARE(target->object(), (QObject*)w3);
750     delete iface; iface = 0;
751
752     iface = target->child(0);
753     QVERIFY(iface != 0);
754     QVERIFY(iface->isValid());
755     QCOMPARE(iface->object(), (QObject*)w31);
756     delete target; target = 0;
757
758     QCOMPARE(iface->navigate(QAccessible::Sibling, -1, &target), -1);
759     QVERIFY(target == 0);
760     QCOMPARE(iface->navigate(QAccessible::Sibling, 0, &target), -1);
761     QVERIFY(target == 0);
762     QCOMPARE(iface->navigate(QAccessible::Sibling, 1, &target), 0);
763     QVERIFY(target != 0);
764     QVERIFY(target->isValid());
765     QCOMPARE(target->object(), (QObject*)w31);
766     delete iface; iface = 0;
767
768     iface = target->parent();
769     QVERIFY(iface != 0);
770     QVERIFY(iface->isValid());
771     QCOMPARE(iface->object(), (QObject*)w3);
772     delete iface; iface = 0;
773     delete target; target = 0;
774
775     delete w;
776     }
777     QTestAccessibility::clearEvents();
778 }
779
780 #define QSETCOMPARE(thetypename, elements, otherelements) \
781     QCOMPARE((QSet<thetypename>() << elements), (QSet<thetypename>() << otherelements))
782
783 static QWidget *createWidgets()
784 {
785     QWidget *w = new QWidget();
786
787     QHBoxLayout *box = new QHBoxLayout(w);
788
789     int i = 0;
790     box->addWidget(new QComboBox(w));
791     box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
792     box->addWidget(new QHeaderView(Qt::Vertical, w));
793     box->addWidget(new QTreeView(w));
794     box->addWidget(new QTreeWidget(w));
795     box->addWidget(new QListView(w));
796     box->addWidget(new QListWidget(w));
797     box->addWidget(new QTableView(w));
798     box->addWidget(new QTableWidget(w));
799     box->addWidget(new QCalendarWidget(w));
800     box->addWidget(new QDialogButtonBox(w));
801     box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
802     box->addWidget(new QFrame(w));
803     box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
804     box->addWidget(new QProgressBar(w));
805     box->addWidget(new QTabWidget(w));
806     box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
807     box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
808     box->addWidget(new QDial(w));
809     box->addWidget(new QScrollBar(w));
810     box->addWidget(new QSlider(w));
811     box->addWidget(new QDateTimeEdit(w));
812     box->addWidget(new QDoubleSpinBox(w));
813     box->addWidget(new QSpinBox(w));
814     box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
815     box->addWidget(new QLCDNumber(w));
816     box->addWidget(new QStackedWidget(w));
817     box->addWidget(new QToolBox(w));
818     box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
819     box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
820
821     /* Not in the list
822      * QAbstractItemView, QGraphicsView, QScrollArea,
823      * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
824      * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
825      */
826     return w;
827 }
828
829 void tst_QAccessibility::accessibleName()
830 {
831     QWidget *toplevel = createWidgets();
832     toplevel->show();
833 #if defined(Q_OS_UNIX)
834     QCoreApplication::processEvents();
835     QTest::qWait(100);
836 #endif
837     QLayout *lout = toplevel->layout();
838     for (int i = 0; i < lout->count(); i++) {
839         QLayoutItem *item = lout->itemAt(i);
840         QWidget *child = item->widget();
841
842         QString name = tr("Widget Name %1").arg(i);
843         child->setAccessibleName(name);
844         QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(child);
845         QCOMPARE(acc->text(QAccessible::Name), name);
846
847         QString desc = tr("Widget Description %1").arg(i);
848         child->setAccessibleDescription(desc);
849         QCOMPARE(acc->text(QAccessible::Description), desc);
850
851     }
852
853     delete toplevel;
854     QTestAccessibility::clearEvents();
855 }
856
857 void tst_QAccessibility::textAttributes()
858 {
859     QTextEdit textEdit;
860     int startOffset;
861     int endOffset;
862     QString attributes;
863     QString text("<html><head></head><body>"
864                  "Hello, <b>this</b> is an <i><b>example</b> text</i>."
865                  "<span style=\"font-family: monospace\">Multiple fonts are used.</span>"
866                  "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used."
867                  "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."
868                  "</body></html>");
869
870     textEdit.setText(text);
871     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit);
872
873     QAccessibleTextInterface *textInterface=interface->textInterface();
874
875     QVERIFY(textInterface);
876     QCOMPARE(textInterface->characterCount(), 112);
877
878     attributes = textInterface->attributes(10, &startOffset, &endOffset);
879     QCOMPARE(startOffset, 7);
880     QCOMPARE(endOffset, 11);
881     attributes.prepend(';');
882     QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
883
884     attributes = textInterface->attributes(18, &startOffset, &endOffset);
885     QCOMPARE(startOffset, 18);
886     QCOMPARE(endOffset, 25);
887     attributes.prepend(';');
888     QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;")));
889     QVERIFY(attributes.contains(QLatin1String(";font-style:italic;")));
890
891     attributes = textInterface->attributes(34, &startOffset, &endOffset);
892     QCOMPARE(startOffset, 31);
893     QCOMPARE(endOffset, 55);
894     attributes.prepend(';');
895     QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";")));
896
897     attributes = textInterface->attributes(65, &startOffset, &endOffset);
898     QCOMPARE(startOffset, 64);
899     QCOMPARE(endOffset, 74);
900     attributes.prepend(';');
901     QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;")));
902
903     attributes = textInterface->attributes(110, &startOffset, &endOffset);
904     QCOMPARE(startOffset, 109);
905     QCOMPARE(endOffset, 111);
906     attributes.prepend(';');
907     QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);")));
908     QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);")));
909 }
910
911 void tst_QAccessibility::hideShowTest()
912 {
913     QWidget * const window = new QWidget();
914     QWidget * const child = new QWidget(window);
915
916     QVERIFY(state(window) & QAccessible::Invisible);
917     QVERIFY(state(child)  & QAccessible::Invisible);
918
919     QTestAccessibility::clearEvents();
920
921     // show() and veryfy that both window and child are not invisible and get ObjectShow events.
922     window->show();
923     QVERIFY(state(window) ^ QAccessible::Invisible);
924     QVERIFY(state(child)  ^ QAccessible::Invisible);
925     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
926     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
927     QTestAccessibility::clearEvents();
928
929     // hide() and veryfy that both window and child are invisible and get ObjectHide events.
930     window->hide();
931     QVERIFY(state(window) & QAccessible::Invisible);
932     QVERIFY(state(child)  & QAccessible::Invisible);
933     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
934     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
935     QTestAccessibility::clearEvents();
936
937     delete window;
938     QTestAccessibility::clearEvents();
939 }
940
941
942 void tst_QAccessibility::actionTest()
943 {
944     {
945     QCOMPARE(QAccessibleActionInterface::pressAction(), QString(QStringLiteral("Press")));
946
947     QWidget *widget = new QWidget;
948     widget->setFocusPolicy(Qt::NoFocus);
949     widget->show();
950
951     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(widget);
952     QVERIFY(interface);
953     QVERIFY(interface->isValid());
954     QAccessibleActionInterface *actions = interface->actionInterface();
955     QVERIFY(actions);
956
957     // no actions by default, except when focusable
958     QCOMPARE(actions->actionNames(), QStringList());
959     widget->setFocusPolicy(Qt::StrongFocus);
960     QCOMPARE(actions->actionNames(), QStringList(QAccessibleActionInterface::setFocusAction()));
961
962     delete interface;
963     delete widget;
964     }
965     QTestAccessibility::clearEvents();
966
967     {
968     QPushButton *button = new QPushButton;
969     button->show();
970     button->clearFocus();
971     QCOMPARE(button->hasFocus(), false);
972     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
973     QAccessibleActionInterface *actions = interface->actionInterface();
974     QVERIFY(actions);
975
976     // Make sure the "primary action" press comes first!
977     QCOMPARE(actions->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
978
979     actions->doAction(QAccessibleActionInterface::setFocusAction());
980     QTest::qWait(500);
981     QCOMPARE(button->hasFocus(), true);
982
983     connect(button, SIGNAL(clicked()), this, SLOT(onClicked()));
984     QCOMPARE(click_count, 0);
985     actions->doAction(QAccessibleActionInterface::pressAction());
986     QTest::qWait(500);
987     QCOMPARE(click_count, 1);
988
989     delete interface;
990     delete button;
991     }
992     QTestAccessibility::clearEvents();
993 }
994
995 void tst_QAccessibility::applicationTest()
996 {
997     QLatin1String name = QLatin1String("My Name");
998     qApp->setApplicationName(name);
999     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp);
1000     QCOMPARE(interface->text(QAccessible::Name), name);
1001     QCOMPARE(interface->role(), QAccessible::Application);
1002     delete interface;
1003 }
1004
1005 void tst_QAccessibility::mainWindowTest()
1006 {
1007     QMainWindow *mw = new QMainWindow;
1008     mw->resize(300, 200);
1009     mw->show(); // triggers layout
1010
1011     QLatin1String name = QLatin1String("I am the main window");
1012     mw->setWindowTitle(name);
1013     QTest::qWaitForWindowShown(mw);
1014     QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
1015
1016     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
1017     QCOMPARE(interface->text(QAccessible::Name), name);
1018     QCOMPARE(interface->role(), QAccessible::Window);
1019     delete interface;
1020     delete mw;
1021     QTestAccessibility::clearEvents();
1022 }
1023
1024 class CounterButton : public QPushButton {
1025     Q_OBJECT
1026 public:
1027     CounterButton(const QString& name, QWidget* parent)
1028         : QPushButton(name, parent), clickCount(0)
1029     {
1030         connect(this, SIGNAL(clicked(bool)), SLOT(incClickCount()));
1031     }
1032     int clickCount;
1033 public Q_SLOTS:
1034     void incClickCount() {
1035         ++clickCount;
1036     }
1037 };
1038
1039 void tst_QAccessibility::buttonTest()
1040 {
1041     QWidget window;
1042     window.setLayout(new QVBoxLayout);
1043
1044     // Standard push button
1045     CounterButton pushButton("Ok", &window);
1046
1047     // toggle button
1048     QPushButton toggleButton("Toggle", &window);
1049     toggleButton.setCheckable(true);
1050
1051     // standard checkbox
1052     QCheckBox checkBox("Check me!", &window);
1053
1054     // tristate checkbox
1055     QCheckBox tristate("Tristate!", &window);
1056     tristate.setTristate(TRUE);
1057
1058     // radiobutton
1059     QRadioButton radio("Radio me!", &window);
1060
1061     // standard toolbutton
1062     QToolButton toolbutton(&window);
1063     toolbutton.setText("Tool");
1064     toolbutton.setMinimumSize(20,20);
1065
1066     // standard toolbutton
1067     QToolButton toggletool(&window);
1068     toggletool.setCheckable(true);
1069     toggletool.setText("Toggle");
1070     toggletool.setMinimumSize(20,20);
1071
1072     // test push button
1073     QAccessibleInterface* interface = QAccessible::queryAccessibleInterface(&pushButton);
1074     QAccessibleActionInterface* actionInterface = interface->actionInterface();
1075     QVERIFY(actionInterface != 0);
1076     QCOMPARE(interface->role(), QAccessible::PushButton);
1077
1078     // buttons only have a click action
1079     QCOMPARE(actionInterface->actionNames().size(), 2);
1080     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::pressAction() << QAccessibleActionInterface::setFocusAction());
1081     QCOMPARE(pushButton.clickCount, 0);
1082     actionInterface->doAction(QAccessibleActionInterface::pressAction());
1083     QTest::qWait(500);
1084     QCOMPARE(pushButton.clickCount, 1);
1085     delete interface;
1086
1087     // test toggle button
1088     interface = QAccessible::queryAccessibleInterface(&toggleButton);
1089     actionInterface = interface->actionInterface();
1090     QCOMPARE(interface->role(), QAccessible::CheckBox);
1091     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1092     QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
1093     QVERIFY(!toggleButton.isChecked());
1094     QVERIFY((interface->state() & QAccessible::Checked) == 0);
1095     actionInterface->doAction(QAccessibleActionInterface::checkAction());
1096     QTest::qWait(500);
1097     QVERIFY(toggleButton.isChecked());
1098     QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
1099     QVERIFY(interface->state() & QAccessible::Checked);
1100     delete interface;
1101
1102     {
1103     // test menu push button
1104     QAction *foo = new QAction("Foo", 0);
1105     foo->setShortcut(QKeySequence("Ctrl+F"));
1106     QMenu *menu = new QMenu();
1107     menu->addAction(foo);
1108     QPushButton menuButton;
1109     menuButton.setMenu(menu);
1110     menuButton.show();
1111     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
1112     QCOMPARE(interface->role(), QAccessible::ButtonMenu);
1113     QVERIFY(interface->state() & QAccessible::HasPopup);
1114     QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction());
1115     // showing the menu enters a new event loop...
1116 //    interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1117 //    QTest::qWait(500);
1118     delete interface;
1119     delete menu;
1120     }
1121
1122     // test check box
1123     interface = QAccessible::queryAccessibleInterface(&checkBox);
1124     actionInterface = interface->actionInterface();
1125     QCOMPARE(interface->role(), QAccessible::CheckBox);
1126     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1127     QVERIFY((interface->state() & QAccessible::Checked) == 0);
1128     actionInterface->doAction(QAccessibleActionInterface::checkAction());
1129     QTest::qWait(500);
1130     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
1131     QVERIFY(interface->state() & QAccessible::Checked);
1132     QVERIFY(checkBox.isChecked());
1133     delete interface;
1134
1135     // test radiobutton
1136     interface = QAccessible::queryAccessibleInterface(&radio);
1137     actionInterface = interface->actionInterface();
1138     QCOMPARE(interface->role(), QAccessible::RadioButton);
1139     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1140     QVERIFY((interface->state() & QAccessible::Checked) == 0);
1141     actionInterface->doAction(QAccessibleActionInterface::checkAction());
1142     QTest::qWait(500);
1143     QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
1144     QVERIFY(interface->state() & QAccessible::Checked);
1145     QVERIFY(checkBox.isChecked());
1146     delete interface;
1147
1148 //    // test standard toolbutton
1149 //    QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
1150 //    QCOMPARE(test->role(), QAccessible::PushButton);
1151 //    QCOMPARE(test->defaultAction(0), QAccessible::Press);
1152 //    QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1153 //    QCOMPARE(test->state(), (int)QAccessible::Normal);
1154 //    test->release();
1155
1156 //    // toggle tool button
1157 //    QVERIFY(QAccessible::queryAccessibleInterface(&toggletool, &test));
1158 //    QCOMPARE(test->role(), QAccessible::CheckBox);
1159 //    QCOMPARE(test->defaultAction(0), QAccessible::Press);
1160 //    QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Check"));
1161 //    QCOMPARE(test->state(), (int)QAccessible::Normal);
1162 //    QVERIFY(test->doAction(QAccessible::Press, 0));
1163 //    QTest::qWait(500);
1164 //    QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Uncheck"));
1165 //    QCOMPARE(test->state(), (int)QAccessible::Checked);
1166 //    test->release();
1167
1168 //    // test menu toolbutton
1169 //    QVERIFY(QAccessible::queryAccessibleInterface(&menuToolButton, &test));
1170 //    QCOMPARE(test->role(), QAccessible::ButtonMenu);
1171 //    QCOMPARE(test->defaultAction(0), 1);
1172 //    QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Open"));
1173 //    QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1174 //    QCOMPARE(test->actionCount(0), 1);
1175 //    QCOMPARE(test->actionText(QAccessible::Press, QAccessible::Name, 0), QString("Press"));
1176 //    test->release();
1177
1178 //    // test split menu toolbutton
1179 //    QVERIFY(QAccessible::queryAccessibleInterface(&splitToolButton, &test));
1180 //    QCOMPARE(test->childCount(), 2);
1181 //    QCOMPARE(test->role(), QAccessible::ButtonDropDown);
1182 //    QCOMPARE(test->role(1), QAccessible::PushButton);
1183 //    QCOMPARE(test->role(2), QAccessible::ButtonMenu);
1184 //    QCOMPARE(test->defaultAction(0), QAccessible::Press);
1185 //    QCOMPARE(test->defaultAction(1), QAccessible::Press);
1186 //    QCOMPARE(test->defaultAction(2), QAccessible::Press);
1187 //    QCOMPARE(test->actionText(test->defaultAction(0), QAccessible::Name, 0), QString("Press"));
1188 //    QCOMPARE(test->state(), (int)QAccessible::HasPopup);
1189 //    QCOMPARE(test->actionCount(0), 1);
1190 //    QCOMPARE(test->actionText(1, QAccessible::Name, 0), QString("Open"));
1191 //    QCOMPARE(test->actionText(test->defaultAction(1), QAccessible::Name, 1), QString("Press"));
1192 //    QCOMPARE(test->state(1), (int)QAccessible::Normal);
1193 //    QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
1194 //    QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
1195 //    test->release();
1196
1197     QTestAccessibility::clearEvents();
1198 }
1199
1200 void tst_QAccessibility::scrollBarTest()
1201 {
1202     QScrollBar *scrollBar  = new QScrollBar(Qt::Horizontal);
1203     QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
1204     QVERIFY(scrollBarInterface);
1205     QVERIFY(scrollBarInterface->state()         & QAccessible::Invisible);
1206     scrollBar->resize(200, 50);
1207     scrollBar->show();
1208     QVERIFY(scrollBarInterface->state()         ^ QAccessible::Invisible);
1209     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
1210     QTestAccessibility::clearEvents();
1211
1212     scrollBar->hide();
1213     QVERIFY(scrollBarInterface->state()         & QAccessible::Invisible);
1214     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
1215     QTestAccessibility::clearEvents();
1216
1217     // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
1218     scrollBar->show();
1219     scrollBar->setMinimum(11);
1220     scrollBar->setMaximum(111);
1221
1222     QAccessibleValueInterface *valueIface = scrollBarInterface->valueInterface();
1223     QVERIFY(valueIface != 0);
1224     QCOMPARE(valueIface->minimumValue().toInt(), scrollBar->minimum());
1225     QCOMPARE(valueIface->maximumValue().toInt(), scrollBar->maximum());
1226     scrollBar->setValue(50);
1227     QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1228     scrollBar->setValue(0);
1229     QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1230     scrollBar->setValue(100);
1231     QCOMPARE(valueIface->currentValue().toInt(), scrollBar->value());
1232     valueIface->setCurrentValue(77);
1233     QCOMPARE(77, scrollBar->value());
1234
1235     const QRect scrollBarRect = scrollBarInterface->rect();
1236     QVERIFY(scrollBarRect.isValid());
1237
1238     delete scrollBarInterface;
1239     delete scrollBar;
1240
1241     QTestAccessibility::clearEvents();
1242 }
1243
1244 void tst_QAccessibility::tabTest()
1245 {
1246     QTabBar *tabBar = new QTabBar();
1247     tabBar->show();
1248
1249     QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabBar);
1250     QVERIFY(interface);
1251     QCOMPARE(interface->childCount(), 2);
1252
1253     // Test that the Invisible bit for the navigation buttons gets set
1254     // and cleared correctly.
1255     QAccessibleInterface *leftButton = interface->child(0);
1256     QCOMPARE(leftButton->role(), QAccessible::PushButton);
1257     QVERIFY(leftButton->state() & QAccessible::Invisible);
1258     delete leftButton;
1259
1260     const int lots = 5;
1261     for (int i = 0; i < lots; ++i)
1262         tabBar->addTab("Foo");
1263
1264     QAccessibleInterface *child1 = interface->child(0);
1265     QAccessibleInterface *child2 = interface->child(1);
1266     QVERIFY(child1);
1267     QCOMPARE(child1->role(), QAccessible::PageTab);
1268     QVERIFY(child2);
1269     QCOMPARE(child2->role(), QAccessible::PageTab);
1270
1271     QVERIFY((child1->state() & QAccessible::Invisible) == false);
1272     tabBar->hide();
1273
1274     QCoreApplication::processEvents();
1275     QTest::qWait(100);
1276
1277     QVERIFY(child1->state() & QAccessible::Invisible);
1278
1279     tabBar->show();
1280     tabBar->setCurrentIndex(0);
1281
1282     // Test that sending a focus action to a tab does not select it.
1283 //    child2->doAction(QAccessible::Focus, 2, QVariantList());
1284     QCOMPARE(tabBar->currentIndex(), 0);
1285
1286     // Test that sending a press action to a tab selects it.
1287     QVERIFY(child2->actionInterface());
1288     QCOMPARE(child2->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1289     QCOMPARE(tabBar->currentIndex(), 0);
1290     child2->actionInterface()->doAction(QAccessibleActionInterface::pressAction());
1291     QCOMPARE(tabBar->currentIndex(), 1);
1292
1293     delete tabBar;
1294     delete interface;
1295     delete child1;
1296     delete child2;
1297     QTestAccessibility::clearEvents();
1298 }
1299
1300 void tst_QAccessibility::tabWidgetTest()
1301 {
1302     QTabWidget *tabWidget = new QTabWidget();
1303     tabWidget->show();
1304
1305     // the interface for the tab is just a container for tabbar and stacked widget
1306     QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(tabWidget);
1307     QVERIFY(interface);
1308     QCOMPARE(interface->childCount(), 2);
1309     QCOMPARE(interface->role(), QAccessible::Client);
1310
1311     // Create pages, check navigation
1312     QLabel *label1 = new QLabel("Page 1", tabWidget);
1313     tabWidget->addTab(label1, "Tab 1");
1314     QLabel *label2 = new QLabel("Page 2", tabWidget);
1315     tabWidget->addTab(label2, "Tab 2");
1316
1317     QCOMPARE(interface->childCount(), 2);
1318
1319     QAccessibleInterface* tabBarInterface = 0;
1320     // there is no special logic to sort the children, so the contents will be 1, the tab bar 2
1321     tabBarInterface = interface->child(1);
1322     QVERIFY(tabBarInterface);
1323     QCOMPARE(tabBarInterface->childCount(), 4);
1324     QCOMPARE(tabBarInterface->role(), QAccessible::PageTabList);
1325
1326     QAccessibleInterface* tabButton1Interface = tabBarInterface->child(0);
1327     QVERIFY(tabButton1Interface);
1328     QCOMPARE(tabButton1Interface->role(), QAccessible::PageTab);
1329     QCOMPARE(tabButton1Interface->text(QAccessible::Name), QLatin1String("Tab 1"));
1330
1331     QAccessibleInterface* tabButton2Interface = tabBarInterface->child(1);
1332     QVERIFY(tabButton1Interface);
1333     QCOMPARE(tabButton2Interface->role(), QAccessible::PageTab);
1334     QCOMPARE(tabButton2Interface->text(QAccessible::Name), QLatin1String("Tab 2"));
1335
1336     QAccessibleInterface* tabButtonLeft = tabBarInterface->child(2);
1337     QVERIFY(tabButtonLeft);
1338     QCOMPARE(tabButtonLeft->role(), QAccessible::PushButton);
1339     QCOMPARE(tabButtonLeft->text(QAccessible::Name), QLatin1String("Scroll Left"));
1340
1341     QAccessibleInterface* tabButtonRight = tabBarInterface->child(3);
1342     QVERIFY(tabButtonRight);
1343     QCOMPARE(tabButtonRight->role(), QAccessible::PushButton);
1344     QCOMPARE(tabButtonRight->text(QAccessible::Name), QLatin1String("Scroll Right"));
1345     delete tabButton1Interface;
1346     delete tabButton2Interface;
1347     delete tabButtonLeft;
1348     delete tabButtonRight;
1349
1350     QAccessibleInterface* stackWidgetInterface = interface->child(0);
1351     QVERIFY(stackWidgetInterface);
1352     QCOMPARE(stackWidgetInterface->childCount(), 2);
1353     QCOMPARE(stackWidgetInterface->role(), QAccessible::LayeredPane);
1354
1355     QAccessibleInterface* stackChild1Interface = stackWidgetInterface->child(0);
1356     QVERIFY(stackChild1Interface);
1357 #ifndef Q_CC_INTEL
1358     QCOMPARE(stackChild1Interface->childCount(), 0);
1359 #endif
1360     QCOMPARE(stackChild1Interface->role(), QAccessible::StaticText);
1361     QCOMPARE(stackChild1Interface->text(QAccessible::Name), QLatin1String("Page 1"));
1362     QCOMPARE(label1, stackChild1Interface->object());
1363
1364     // Navigation in stack widgets should be consistent
1365     QAccessibleInterface* parent = stackChild1Interface->parent();
1366     QVERIFY(parent);
1367 #ifndef Q_CC_INTEL
1368     QCOMPARE(parent->childCount(), 2);
1369 #endif
1370     QCOMPARE(parent->role(), QAccessible::LayeredPane);
1371     delete parent;
1372
1373     QAccessibleInterface* stackChild2Interface = stackWidgetInterface->child(1);
1374     QVERIFY(stackChild2Interface);
1375     QCOMPARE(stackChild2Interface->childCount(), 0);
1376     QCOMPARE(stackChild2Interface->role(), QAccessible::StaticText);
1377     QCOMPARE(label2, stackChild2Interface->object());
1378     QCOMPARE(label2->text(), stackChild2Interface->text(QAccessible::Name));
1379
1380     parent = stackChild2Interface->parent();
1381     QVERIFY(parent);
1382 #ifndef Q_CC_INTEL
1383     QCOMPARE(parent->childCount(), 2);
1384 #endif
1385     QCOMPARE(parent->role(), QAccessible::LayeredPane);
1386     delete parent;
1387
1388     delete tabBarInterface;
1389     delete stackChild1Interface;
1390     delete stackChild2Interface;
1391     delete stackWidgetInterface;
1392     delete interface;
1393     delete tabWidget;
1394     QTestAccessibility::clearEvents();
1395 }
1396
1397 void tst_QAccessibility::menuTest()
1398 {
1399     {
1400     QMainWindow mw;
1401     mw.resize(300, 200);
1402     QMenu *file = mw.menuBar()->addMenu("&File");
1403     QMenu *fileNew = file->addMenu("&New...");
1404     fileNew->menuAction()->setShortcut(tr("Ctrl+N"));
1405     fileNew->addAction("Text file");
1406     fileNew->addAction("Image file");
1407     file->addAction("&Open")->setShortcut(tr("Ctrl+O"));
1408     file->addAction("&Save")->setShortcut(tr("Ctrl+S"));
1409     file->addSeparator();
1410     file->addAction("E&xit")->setShortcut(tr("Alt+F4"));
1411
1412     QMenu *edit = mw.menuBar()->addMenu("&Edit");
1413     edit->addAction("&Undo")->setShortcut(tr("Ctrl+Z"));
1414     edit->addAction("&Redo")->setShortcut(tr("Ctrl+Y"));
1415     edit->addSeparator();
1416     edit->addAction("Cu&t")->setShortcut(tr("Ctrl+X"));
1417     edit->addAction("&Copy")->setShortcut(tr("Ctrl+C"));
1418     edit->addAction("&Paste")->setShortcut(tr("Ctrl+V"));
1419     edit->addAction("&Delete")->setShortcut(tr("Del"));
1420     edit->addSeparator();
1421     edit->addAction("Pr&operties");
1422
1423     mw.menuBar()->addSeparator();
1424
1425     QMenu *help = mw.menuBar()->addMenu("&Help");
1426     help->addAction("&Contents");
1427     help->addAction("&About");
1428
1429     mw.menuBar()->addAction("Action!");
1430
1431     mw.show(); // triggers layout
1432     QTest::qWait(100);
1433
1434     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw.menuBar());
1435     QCOMPARE(verifyHierarchy(interface),  0);
1436
1437     QVERIFY(interface);
1438     QCOMPARE(interface->childCount(), 5);
1439     QCOMPARE(interface->role(), QAccessible::MenuBar);
1440
1441     QAccessibleInterface *iFile = interface->child(0);
1442     QAccessibleInterface *iEdit = interface->child(1);
1443     QAccessibleInterface *iSeparator = interface->child(2);
1444     QAccessibleInterface *iHelp = interface->child(3);
1445     QAccessibleInterface *iAction = interface->child(4);
1446
1447     QCOMPARE(iFile->role(), QAccessible::MenuItem);
1448     QCOMPARE(iEdit->role(), QAccessible::MenuItem);
1449     QCOMPARE(iSeparator->role(), QAccessible::Separator);
1450     QCOMPARE(iHelp->role(), QAccessible::MenuItem);
1451     QCOMPARE(iAction->role(), QAccessible::MenuItem);
1452 #ifndef Q_WS_MAC
1453 #ifdef Q_OS_WINCE
1454     if (!IsValidCEPlatform())
1455         QSKIP("Tests do not work on Mobile platforms due to native menus");
1456 #endif
1457     QCOMPARE(mw.mapFromGlobal(interface->rect().topLeft()), mw.menuBar()->geometry().topLeft());
1458     QCOMPARE(interface->rect().size(), mw.menuBar()->size());
1459
1460     QVERIFY(interface->rect().contains(iFile->rect()));
1461     QVERIFY(interface->rect().contains(iEdit->rect()));
1462     // QVERIFY(interface->rect().contains(childSeparator->rect())); //separator might be invisible
1463     QVERIFY(interface->rect().contains(iHelp->rect()));
1464     QVERIFY(interface->rect().contains(iAction->rect()));
1465 #endif
1466
1467     QCOMPARE(iFile->text(QAccessible::Name), QString("File"));
1468     QCOMPARE(iEdit->text(QAccessible::Name), QString("Edit"));
1469     QCOMPARE(iSeparator->text(QAccessible::Name), QString());
1470     QCOMPARE(iHelp->text(QAccessible::Name), QString("Help"));
1471     QCOMPARE(iAction->text(QAccessible::Name), QString("Action!"));
1472
1473 // TODO: Currently not working, task to fix is #100019.
1474 #ifndef Q_OS_MAC
1475     QCOMPARE(iFile->text(QAccessible::Accelerator), tr("Alt+F"));
1476     QCOMPARE(iEdit->text(QAccessible::Accelerator), tr("Alt+E"));
1477     QCOMPARE(iSeparator->text(QAccessible::Accelerator), QString());
1478     QCOMPARE(iHelp->text(QAccessible::Accelerator), tr("Alt+H"));
1479     QCOMPARE(iAction->text(QAccessible::Accelerator), QString());
1480 #endif
1481
1482     QVERIFY(iFile->actionInterface());
1483
1484     QCOMPARE(iFile->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1485     QCOMPARE(iSeparator->actionInterface()->actionNames(), QStringList());
1486     QCOMPARE(iHelp->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1487     QCOMPARE(iAction->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1488
1489     bool menuFade = qApp->isEffectEnabled(Qt::UI_FadeMenu);
1490     int menuFadeDelay = 300;
1491     iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1492     if(menuFade)
1493         QTest::qWait(menuFadeDelay);
1494     QVERIFY(file->isVisible() && !edit->isVisible() && !help->isVisible());
1495     iEdit->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1496     if(menuFade)
1497         QTest::qWait(menuFadeDelay);
1498     QVERIFY(!file->isVisible() && edit->isVisible() && !help->isVisible());
1499     iHelp->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1500     if(menuFade)
1501         QTest::qWait(menuFadeDelay);
1502     QVERIFY(!file->isVisible() && !edit->isVisible() && help->isVisible());
1503     iAction->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1504     if(menuFade)
1505         QTest::qWait(menuFadeDelay);
1506     QVERIFY(!file->isVisible() && !edit->isVisible() && !help->isVisible());
1507
1508     QVERIFY(interface->actionInterface());
1509     QCOMPARE(interface->actionInterface()->actionNames(), QStringList());
1510     delete interface;
1511     interface = QAccessible::queryAccessibleInterface(file);
1512     QCOMPARE(interface->childCount(), 5);
1513     QCOMPARE(interface->role(), QAccessible::PopupMenu);
1514
1515     QAccessibleInterface *iFileNew = interface->child(0);
1516     QAccessibleInterface *iFileOpen = interface->child(1);
1517     QAccessibleInterface *iFileSave = interface->child(2);
1518     QAccessibleInterface *iFileSeparator = interface->child(3);
1519     QAccessibleInterface *iFileExit = interface->child(4);
1520
1521     QCOMPARE(iFileNew->role(), QAccessible::MenuItem);
1522     QCOMPARE(iFileOpen->role(), QAccessible::MenuItem);
1523     QCOMPARE(iFileSave->role(), QAccessible::MenuItem);
1524     QCOMPARE(iFileSeparator->role(), QAccessible::Separator);
1525     QCOMPARE(iFileExit->role(), QAccessible::MenuItem);
1526     QCOMPARE(iFileNew->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
1527     QCOMPARE(iFileOpen->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1528     QCOMPARE(iFileSave->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1529     QCOMPARE(iFileSeparator->actionInterface()->actionNames(), QStringList());
1530     QCOMPARE(iFileExit->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::pressAction());
1531
1532     QAccessibleInterface *iface = 0;
1533     QAccessibleInterface *iface2 = 0;
1534
1535     // traverse siblings with navigate(Sibling, ...)
1536     int entry;
1537     iface = interface->child(0);
1538     QVERIFY(iface);
1539     QCOMPARE(iface->role(), QAccessible::MenuItem);
1540
1541     QAccessible::Role fileRoles[5] = {
1542         QAccessible::MenuItem,
1543         QAccessible::MenuItem,
1544         QAccessible::MenuItem,
1545         QAccessible::Separator,
1546         QAccessible::MenuItem
1547     };
1548     for (int child = 0; child < 5; ++child) {
1549         entry = iface->navigate(QAccessible::Sibling, child + 1, &iface2);
1550         QCOMPARE(entry, 0);
1551         QVERIFY(iface2);
1552         QCOMPARE(iface2->role(), fileRoles[child]);
1553         delete iface2;
1554     }
1555     delete iface;
1556
1557     // traverse menu items with navigate(Down, ...)
1558     iface = interface->child(0);
1559     QVERIFY(iface);
1560     QCOMPARE(iface->role(), QAccessible::MenuItem);
1561
1562     for (int child = 0; child < 4; ++child) {
1563         entry = iface->navigate(QAccessible::Down, 1, &iface2);
1564         delete iface;
1565         iface = iface2;
1566         QCOMPARE(entry, 0);
1567         QVERIFY(iface);
1568         QCOMPARE(iface->role(), fileRoles[child + 1]);
1569     }
1570     delete iface;
1571
1572     // traverse menu items with navigate(Up, ...)
1573     iface = interface->child(interface->childCount() - 1);
1574     QVERIFY(iface);
1575     QCOMPARE(iface->role(), QAccessible::MenuItem);
1576
1577     for (int child = 3; child >= 0; --child) {
1578         entry = iface->navigate(QAccessible::Up, 1, &iface2);
1579         delete iface;
1580         iface = iface2;
1581         QCOMPARE(entry, 0);
1582         QVERIFY(iface);
1583         QCOMPARE(iface->role(), fileRoles[child]);
1584     }
1585     delete iface;
1586
1587     // "New" item
1588     iface = interface->child(0);
1589     QVERIFY(iface);
1590     QCOMPARE(iface->role(), QAccessible::MenuItem);
1591
1592     // "New" menu
1593     iface2 = iface->child(0);
1594     delete iface;
1595     iface = iface2;
1596     QCOMPARE(entry, 0);
1597     QVERIFY(iface);
1598     QCOMPARE(iface->role(), QAccessible::PopupMenu);
1599
1600     // "Text file" menu item
1601     iface2 = iface->child(0);
1602     delete iface;
1603     iface = iface2;
1604     QVERIFY(iface);
1605     QCOMPARE(iface->role(), QAccessible::MenuItem);
1606
1607     delete iface;
1608
1609     // move mouse pointer away, since that might influence the
1610     // subsequent tests
1611     QTest::mouseMove(&mw, QPoint(-1, -1));
1612     QTest::qWait(100);
1613     if (menuFade)
1614         QTest::qWait(menuFadeDelay);
1615
1616     iFile->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1617     iFileNew->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
1618
1619     QVERIFY(file->isVisible());
1620     QVERIFY(fileNew->isVisible());
1621     QVERIFY(!edit->isVisible());
1622     QVERIFY(!help->isVisible());
1623
1624     QTestAccessibility::clearEvents();
1625     mw.hide();
1626
1627     delete iFile;
1628     delete iFileNew;
1629     delete iFileOpen;
1630     delete iFileSave;
1631     delete iFileSeparator;
1632     delete iFileExit;
1633
1634     // Do not crash if the menu don't have a parent
1635     QMenu *menu = new QMenu;
1636     menu->addAction(QLatin1String("one"));
1637     menu->addAction(QLatin1String("two"));
1638     menu->addAction(QLatin1String("three"));
1639     iface = QAccessible::queryAccessibleInterface(menu);
1640     iface2 = iface->parent();
1641     QVERIFY(iface2);
1642     QCOMPARE(iface2->role(), QAccessible::Application);
1643     // caused a *crash*
1644     iface2->state();
1645     delete iface2;
1646     delete iface;
1647     delete menu;
1648
1649     }
1650     QTestAccessibility::clearEvents();
1651 }
1652
1653 void tst_QAccessibility::spinBoxTest()
1654 {
1655     QSpinBox * const spinBox = new QSpinBox();
1656     spinBox->setValue(3);
1657     spinBox->show();
1658
1659     QAccessibleInterface * const interface = QAccessible::queryAccessibleInterface(spinBox);
1660     QVERIFY(interface);
1661     QCOMPARE(interface->role(), QAccessible::SpinBox);
1662
1663     const QRect widgetRect = spinBox->geometry();
1664     const QRect accessibleRect = interface->rect();
1665     QCOMPARE(accessibleRect, widgetRect);
1666     QCOMPARE(interface->text(QAccessible::Value), QLatin1String("3"));
1667
1668     // one child, the line edit
1669     const int numChildren = interface->childCount();
1670     QCOMPARE(numChildren, 1);
1671     QAccessibleInterface *lineEdit = interface->child(0);
1672
1673     QCOMPARE(lineEdit->role(), QAccessible::EditableText);
1674     QCOMPARE(lineEdit->text(QAccessible::Value), QLatin1String("3"));
1675     delete lineEdit;
1676
1677     QVERIFY(interface->valueInterface());
1678     QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3);
1679     interface->valueInterface()->setCurrentValue(23);
1680     QCOMPARE(interface->valueInterface()->currentValue().toInt(), 23);
1681     QCOMPARE(spinBox->value(), 23);
1682
1683     spinBox->setFocus();
1684     QTestAccessibility::clearEvents();
1685     QTest::keyPress(spinBox, Qt::Key_Up);
1686     QTest::qWait(200);
1687     EventList events = QTestAccessibility::events();
1688     QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
1689     QVERIFY(events.contains(expectedEvent));
1690     delete spinBox;
1691     QTestAccessibility::clearEvents();
1692 }
1693
1694 void tst_QAccessibility::doubleSpinBoxTest()
1695 {
1696     QDoubleSpinBox *doubleSpinBox = new QDoubleSpinBox;
1697     doubleSpinBox->show();
1698
1699     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
1700     QVERIFY(interface);
1701
1702     const QRect widgetRect = doubleSpinBox->geometry();
1703     const QRect accessibleRect = interface->rect();
1704     QCOMPARE(accessibleRect, widgetRect);
1705
1706     // Test that we get valid rects for all the spinbox child interfaces.
1707     const int numChildren = interface->childCount();
1708     for (int i = 0; i < numChildren; ++i) {
1709         QAccessibleInterface *childIface = interface->child(i);
1710         const QRect childRect = childIface->rect();
1711         QVERIFY(childRect.isValid());
1712         delete childIface;
1713     }
1714
1715     delete doubleSpinBox;
1716     QTestAccessibility::clearEvents();
1717 }
1718
1719 void tst_QAccessibility::textEditTest()
1720 {
1721     {
1722     QTextEdit edit;
1723     int startOffset;
1724     int endOffset;
1725     QString text = "hello world\nhow are you today?\n";
1726     edit.setText(text);
1727     edit.show();
1728
1729     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
1730     QCOMPARE(iface->text(QAccessible::Value), text);
1731     QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1732     QCOMPARE(startOffset, 6);
1733     QCOMPARE(endOffset, 11);
1734     QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1735     QCOMPARE(startOffset, 12);
1736     QCOMPARE(endOffset, 30);
1737     QCOMPARE(iface->textInterface()->characterCount(), 31);
1738     QFontMetrics fm(edit.font());
1739     QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
1740     QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
1741     QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
1742     }
1743     QTestAccessibility::clearEvents();
1744 }
1745
1746 void tst_QAccessibility::textBrowserTest()
1747 {
1748     {
1749     QTextBrowser textBrowser;
1750     QString text = QLatin1String("Hello world\nhow are you today?\n");
1751     textBrowser.setText(text);
1752     textBrowser.show();
1753
1754     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&textBrowser);
1755     QVERIFY(iface);
1756     QCOMPARE(iface->role(), QAccessible::StaticText);
1757     QCOMPARE(iface->text(QAccessible::Value), text);
1758     int startOffset;
1759     int endOffset;
1760     QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
1761     QCOMPARE(startOffset, 6);
1762     QCOMPARE(endOffset, 11);
1763     QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
1764     QCOMPARE(startOffset, 12);
1765     QCOMPARE(endOffset, 30);
1766     QCOMPARE(iface->textInterface()->characterCount(), 31);
1767     }
1768     QTestAccessibility::clearEvents();
1769 }
1770
1771 void tst_QAccessibility::mdiAreaTest()
1772 {
1773     {
1774     QMdiArea mdiArea;
1775     mdiArea.resize(400,300);
1776     mdiArea.show();
1777     const int subWindowCount = 3;
1778     for (int i = 0; i < subWindowCount; ++i)
1779         mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show();
1780
1781     QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1782     QCOMPARE(subWindows.count(), subWindowCount);
1783
1784     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea);
1785     QVERIFY(interface);
1786     QCOMPARE(interface->childCount(), subWindowCount);
1787
1788     // Right, right, right, ...
1789     for (int i = 0; i < subWindowCount; ++i) {
1790         QAccessibleInterface *destination = 0;
1791         int index = interface->navigate(QAccessible::Right, i + 1, &destination);
1792         if (i == subWindowCount - 1) {
1793             QVERIFY(!destination);
1794             QCOMPARE(index, -1);
1795         } else {
1796             QVERIFY(destination);
1797             QCOMPARE(index, 0);
1798             QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
1799             delete destination;
1800         }
1801     }
1802
1803     // Left, left, left, ...
1804     for (int i = subWindowCount; i > 0; --i) {
1805         QAccessibleInterface *destination = 0;
1806         int index = interface->navigate(QAccessible::Left, i, &destination);
1807         if (i == 1) {
1808             QVERIFY(!destination);
1809             QCOMPARE(index, -1);
1810         } else {
1811             QVERIFY(destination);
1812             QCOMPARE(index, 0);
1813             QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
1814             delete destination;
1815         }
1816     }
1817     // ### Add test for Up and Down.
1818
1819     }
1820     QTestAccessibility::clearEvents();
1821 }
1822
1823 void tst_QAccessibility::mdiSubWindowTest()
1824 {
1825     {
1826     QMdiArea mdiArea;
1827     mdiArea.show();
1828     qApp->setActiveWindow(&mdiArea);
1829 #if defined(Q_OS_UNIX)
1830     QCoreApplication::processEvents();
1831     QTest::qWait(150);
1832 #endif
1833
1834     bool isSubWindowsPlacedNextToEachOther = false;
1835     const int subWindowCount =  5;
1836     for (int i = 0; i < subWindowCount; ++i) {
1837         QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
1838         window->show();
1839         // Parts of this test requires that the sub windows are placed next
1840         // to each other. In order to achieve that QMdiArea must have
1841         // a width which is larger than subWindow->width() * subWindowCount.
1842         if (i == 0) {
1843             int minimumWidth = window->width() * subWindowCount + 20;
1844             mdiArea.resize(mdiArea.size().expandedTo(QSize(minimumWidth, 0)));
1845 #if defined(Q_OS_UNIX)
1846             QCoreApplication::processEvents();
1847             QTest::qWait(100);
1848 #endif
1849             if (mdiArea.width() >= minimumWidth)
1850                 isSubWindowsPlacedNextToEachOther = true;
1851         }
1852     }
1853
1854     QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
1855     QCOMPARE(subWindows.count(), subWindowCount);
1856
1857     QMdiSubWindow *testWindow = subWindows.at(3);
1858     QVERIFY(testWindow);
1859     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(testWindow);
1860
1861     // childCount
1862     QVERIFY(interface);
1863     QCOMPARE(interface->childCount(), 1);
1864
1865     // setText / text
1866     QCOMPARE(interface->text(QAccessible::Name), QString());
1867     testWindow->setWindowTitle(QLatin1String("ReplaceMe"));
1868     QCOMPARE(interface->text(QAccessible::Name), QLatin1String("ReplaceMe"));
1869     interface->setText(QAccessible::Name, QLatin1String("TitleSetOnWindow"));
1870     QCOMPARE(interface->text(QAccessible::Name), QLatin1String("TitleSetOnWindow"));
1871
1872     mdiArea.setActiveSubWindow(testWindow);
1873
1874     // state
1875     QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused
1876                                | QAccessible::Movable | QAccessible::Sizeable;
1877     QCOMPARE(interface->state(), state);
1878     const QRect originalGeometry = testWindow->geometry();
1879     testWindow->showMaximized();
1880     state &= (uint)~QAccessible::Sizeable;
1881     state &= (uint)~QAccessible::Movable;
1882     QCOMPARE(interface->state(), state);
1883     testWindow->showNormal();
1884     testWindow->move(-10, 0);
1885     QVERIFY(interface->state() & QAccessible::Offscreen);
1886     testWindow->setVisible(false);
1887     QVERIFY(interface->state() & QAccessible::Invisible);
1888     testWindow->setVisible(true);
1889     testWindow->setEnabled(false);
1890     QVERIFY(interface->state() & QAccessible::Unavailable);
1891     testWindow->setEnabled(true);
1892     qApp->setActiveWindow(&mdiArea);
1893     mdiArea.setActiveSubWindow(testWindow);
1894     testWindow->setFocus();
1895     QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
1896     QVERIFY(interface->state() & QAccessible::Focused);
1897     testWindow->setGeometry(originalGeometry);
1898
1899     if (isSubWindowsPlacedNextToEachOther) {
1900         // This part of the test can only be run if the sub windows are
1901         // placed next to each other.
1902         QAccessibleInterface *destination = interface->child(0);
1903         QVERIFY(destination);
1904         QCOMPARE(destination->object(), (QObject*)testWindow->widget());
1905         delete destination;
1906         QCOMPARE(interface->navigate(QAccessible::Left, 0, &destination), 0);
1907         QVERIFY(destination);
1908         QCOMPARE(destination->object(), (QObject*)subWindows.at(2));
1909         delete destination;
1910         QCOMPARE(interface->navigate(QAccessible::Right, 0, &destination), 0);
1911         QVERIFY(destination);
1912         QCOMPARE(destination->object(), (QObject*)subWindows.at(4));
1913         delete destination;
1914     }
1915
1916     // rect
1917     const QPoint globalPos = testWindow->mapToGlobal(QPoint(0, 0));
1918     QCOMPARE(interface->rect(), QRect(globalPos, testWindow->size()));
1919     testWindow->hide();
1920     QCOMPARE(interface->rect(), QRect());
1921     QCOMPARE(childRect(interface), QRect());
1922     testWindow->showMinimized();
1923     QCOMPARE(childRect(interface), QRect());
1924     testWindow->showNormal();
1925     testWindow->widget()->hide();
1926     QCOMPARE(childRect(interface), QRect());
1927     testWindow->widget()->show();
1928     const QRect widgetGeometry = testWindow->contentsRect();
1929     const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
1930                                           globalPos.y() + widgetGeometry.y());
1931     QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
1932
1933     // childAt
1934     QCOMPARE(interface->childAt(-10, 0), -1);
1935     QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0);
1936     QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1);
1937     testWindow->widget()->hide();
1938     QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0);
1939
1940     }
1941     QTestAccessibility::clearEvents();
1942 }
1943
1944 void tst_QAccessibility::lineEditTest()
1945 {
1946     QLineEdit *le = new QLineEdit;
1947     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
1948     QVERIFY(iface);
1949     le->show();
1950
1951     QApplication::processEvents();
1952     QCOMPARE(iface->childCount(), 0);
1953     QVERIFY(iface->state() & QAccessible::Sizeable);
1954     QVERIFY(iface->state() & QAccessible::Movable);
1955     QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1956     QVERIFY(iface->state() & QAccessible::Selectable);
1957     QVERIFY(iface->state() & QAccessible::HasPopup);
1958     QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1959
1960     QString secret(QLatin1String("secret"));
1961     le->setText(secret);
1962     le->setEchoMode(QLineEdit::Normal);
1963     QVERIFY(!(iface->state() & QAccessible::Protected));
1964     QCOMPARE(iface->text(QAccessible::Value), secret);
1965     le->setEchoMode(QLineEdit::NoEcho);
1966     QVERIFY(iface->state() & QAccessible::Protected);
1967     QVERIFY(iface->text(QAccessible::Value).isEmpty());
1968     le->setEchoMode(QLineEdit::Password);
1969     QVERIFY(iface->state() & QAccessible::Protected);
1970     QVERIFY(iface->text(QAccessible::Value).isEmpty());
1971     le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
1972     QVERIFY(iface->state() & QAccessible::Protected);
1973     QVERIFY(iface->text(QAccessible::Value).isEmpty());
1974     le->setEchoMode(QLineEdit::Normal);
1975     QVERIFY(!(iface->state() & QAccessible::Protected));
1976     QCOMPARE(iface->text(QAccessible::Value), secret);
1977
1978     QWidget *toplevel = new QWidget;
1979     le->setParent(toplevel);
1980     toplevel->show();
1981     QApplication::processEvents();
1982     QVERIFY(!(iface->state() & QAccessible::Sizeable));
1983     QVERIFY(!(iface->state() & QAccessible::Movable));
1984     QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow());
1985     QVERIFY(iface->state() & QAccessible::Selectable);
1986     QVERIFY(iface->state() & QAccessible::HasPopup);
1987     QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus());
1988
1989     QLineEdit *le2 = new QLineEdit(toplevel);
1990     le2->show();
1991     QTest::qWait(100);
1992     le2->activateWindow();
1993     QTest::qWait(100);
1994     le->setFocus(Qt::TabFocusReason);
1995     QTestAccessibility::clearEvents();
1996     le2->setFocus(Qt::TabFocusReason);
1997     QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
1998
1999     le->setText(QLatin1String("500"));
2000     le->setValidator(new QIntValidator());
2001     iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
2002     QCOMPARE(le->text(), QLatin1String("500"));
2003
2004     delete iface;
2005     delete le;
2006     delete le2;
2007     QTestAccessibility::clearEvents();
2008
2009     // IA2
2010     QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde";
2011     QLineEdit *le3 = new QLineEdit(cite, toplevel);
2012     iface = QAccessible::queryAccessibleInterface(le3);
2013     QAccessibleTextInterface* textIface = iface->textInterface();
2014     le3->deselect();
2015     le3->setCursorPosition(3);
2016     QCOMPARE(textIface->cursorPosition(), 3);
2017     QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
2018     QCOMPARE(textIface->selectionCount(), 0);
2019     QTestAccessibility::clearEvents();
2020
2021     int start, end;
2022     QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always"));
2023     QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I"));
2024     QCOMPARE(start, 0);
2025     QCOMPARE(end, 1);
2026     QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString());
2027     QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" "));
2028     QCOMPARE(start, 1);
2029     QCOMPARE(end, 2);
2030
2031     QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a"));
2032     QCOMPARE(start, 5);
2033     QCOMPARE(end, 6);
2034     QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w"));
2035     QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y"));
2036
2037     QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2038     QCOMPARE(start, 2);
2039     QCOMPARE(end, 8);
2040
2041     QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2042     QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always"));
2043     QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2044     QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
2045     QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
2046
2047     QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2048     QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
2049     QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2050     QCOMPARE(start, 0);
2051     QCOMPARE(end, 30);
2052
2053     QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. "));
2054     QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. "));
2055
2056     QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite);
2057     QCOMPARE(start, 0);
2058     QCOMPARE(end, cite.length());
2059     QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
2060     QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
2061
2062     delete iface;
2063     delete toplevel;
2064     QTestAccessibility::clearEvents();
2065 }
2066
2067 void tst_QAccessibility::workspaceTest()
2068 {
2069     {
2070     QWorkspace workspace;
2071     workspace.resize(400,300);
2072     workspace.show();
2073     const int subWindowCount =  3;
2074     for (int i = 0; i < subWindowCount; ++i) {
2075         QWidget *window = workspace.addWindow(new QWidget);
2076         if (i > 0)
2077             window->move(window->x() + 1, window->y());
2078         window->show();
2079         window->resize(70, window->height());
2080     }
2081
2082     QWidgetList subWindows = workspace.windowList();
2083     QCOMPARE(subWindows.count(), subWindowCount);
2084
2085     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
2086     QVERIFY(interface);
2087     QCOMPARE(interface->childCount(), subWindowCount);
2088
2089     // Right, right, right, ...
2090     for (int i = 0; i < subWindowCount; ++i) {
2091         QAccessibleInterface *destination = 0;
2092         int index = interface->navigate(QAccessible::Right, i + 1, &destination);
2093         if (i == subWindowCount - 1) {
2094             QVERIFY(!destination);
2095             QCOMPARE(index, -1);
2096         } else {
2097             QVERIFY(destination);
2098             QCOMPARE(index, 0);
2099             QCOMPARE(destination->object(), (QObject*)subWindows.at(i + 1));
2100             delete destination;
2101         }
2102     }
2103
2104     // Left, left, left, ...
2105     for (int i = subWindowCount; i > 0; --i) {
2106         QAccessibleInterface *destination = 0;
2107         int index = interface->navigate(QAccessible::Left, i, &destination);
2108         if (i == 1) {
2109             QVERIFY(!destination);
2110             QCOMPARE(index, -1);
2111         } else {
2112             QVERIFY(destination);
2113             QCOMPARE(index, 0);
2114             QCOMPARE(destination->object(), (QObject*)subWindows.at(i - 2));
2115             delete destination;
2116         }
2117     }
2118     // ### Add test for Up and Down.
2119
2120     }
2121     QTestAccessibility::clearEvents();
2122 }
2123
2124 void tst_QAccessibility::dialogButtonBoxTest()
2125 {
2126     {
2127     QDialogButtonBox box(QDialogButtonBox::Reset |
2128                          QDialogButtonBox::Help |
2129                          QDialogButtonBox::Ok, Qt::Horizontal);
2130
2131
2132     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2133     QVERIFY(iface);
2134     box.show();
2135 #if defined(Q_OS_UNIX)
2136     QCoreApplication::processEvents();
2137     QTest::qWait(100);
2138 #endif
2139
2140     QApplication::processEvents();
2141     QCOMPARE(iface->childCount(), 3);
2142     QCOMPARE(iface->role(), QAccessible::Grouping);
2143     QStringList actualOrder;
2144     QAccessibleInterface *child;
2145     QAccessibleInterface *leftmost;
2146     child = iface->child(0);
2147     QCOMPARE(child->role(), QAccessible::PushButton);
2148
2149     // first find the leftmost button
2150     while (child->navigate(QAccessible::Left, 1, &leftmost) != -1) {
2151         delete child;
2152         child = leftmost;
2153     }
2154     leftmost = child;
2155
2156     // then traverse from left to right to find the correct order of the buttons
2157     int right = 0;
2158     while (right != -1) {
2159         actualOrder << leftmost->text(QAccessible::Name);
2160         right = leftmost->navigate(QAccessible::Right, 1, &child);
2161         delete leftmost;
2162         leftmost = child;
2163     }
2164
2165     QStringList expectedOrder;
2166     QDialogButtonBox::ButtonLayout btnlout =
2167         QDialogButtonBox::ButtonLayout(QApplication::style()->styleHint(QStyle::SH_DialogButtonLayout));
2168     switch (btnlout) {
2169     case QDialogButtonBox::WinLayout:
2170         expectedOrder << QDialogButtonBox::tr("Reset")
2171                       << QDialogButtonBox::tr("OK")
2172                       << QDialogButtonBox::tr("Help");
2173         break;
2174     case QDialogButtonBox::GnomeLayout:
2175     case QDialogButtonBox::KdeLayout:
2176     case QDialogButtonBox::MacLayout:
2177         expectedOrder << QDialogButtonBox::tr("Help")
2178                       << QDialogButtonBox::tr("Reset")
2179                       << QDialogButtonBox::tr("OK");
2180         break;
2181     }
2182     QCOMPARE(actualOrder, expectedOrder);
2183     delete iface;
2184     QApplication::processEvents();
2185     QTestAccessibility::clearEvents();
2186     }
2187
2188     {
2189     QDialogButtonBox box(QDialogButtonBox::Reset |
2190                          QDialogButtonBox::Help |
2191                          QDialogButtonBox::Ok, Qt::Horizontal);
2192
2193
2194     // Test up and down navigation
2195     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&box);
2196     QVERIFY(iface);
2197     box.setOrientation(Qt::Vertical);
2198     box.show();
2199 #if defined(Q_OS_UNIX)
2200     QCoreApplication::processEvents();
2201     QTest::qWait(100);
2202 #endif
2203
2204     QApplication::processEvents();
2205     QAccessibleInterface *child;
2206     QStringList actualOrder;
2207     child = iface->child(0);
2208     // first find the topmost button
2209     QAccessibleInterface *other;
2210     while (child->navigate(QAccessible::Up, 1, &other) != -1) {
2211         delete child;
2212         child = other;
2213     }
2214     other = child;
2215
2216     // then traverse from top to bottom to find the correct order of the buttons
2217     actualOrder.clear();
2218     int right = 0;
2219     while (right != -1) {
2220         actualOrder << other->text(QAccessible::Name);
2221         right = other->navigate(QAccessible::Down, 1, &child);
2222         delete other;
2223         other = child;
2224     }
2225
2226     QStringList expectedOrder;
2227     expectedOrder << QDialogButtonBox::tr("OK")
2228                   << QDialogButtonBox::tr("Reset")
2229                   << QDialogButtonBox::tr("Help");
2230
2231     QCOMPARE(actualOrder, expectedOrder);
2232     delete iface;
2233     QApplication::processEvents();
2234
2235     }
2236     QTestAccessibility::clearEvents();
2237 }
2238
2239 void tst_QAccessibility::dialTest()
2240 {
2241     {
2242     QDial dial;
2243     dial.setMinimum(23);
2244     dial.setMaximum(121);
2245     dial.setValue(42);
2246     QCOMPARE(dial.value(), 42);
2247     dial.show();
2248
2249     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&dial);
2250     QVERIFY(interface);
2251     QCOMPARE(interface->childCount(), 0);
2252
2253     QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value()));
2254     QCOMPARE(interface->rect(), dial.geometry());
2255
2256     QAccessibleValueInterface *valueIface = interface->valueInterface();
2257     QVERIFY(valueIface != 0);
2258     QCOMPARE(valueIface->minimumValue().toInt(), dial.minimum());
2259     QCOMPARE(valueIface->maximumValue().toInt(), dial.maximum());
2260     QCOMPARE(valueIface->currentValue().toInt(), 42);
2261     dial.setValue(50);
2262     QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2263     dial.setValue(0);
2264     QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2265     dial.setValue(100);
2266     QCOMPARE(valueIface->currentValue().toInt(), dial.value());
2267     valueIface->setCurrentValue(77);
2268     QCOMPARE(77, dial.value());
2269     }
2270     QTestAccessibility::clearEvents();
2271 }
2272
2273 void tst_QAccessibility::rubberBandTest()
2274 {
2275     QRubberBand rubberBand(QRubberBand::Rectangle);
2276     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&rubberBand);
2277     QVERIFY(interface);
2278     QCOMPARE(interface->role(), QAccessible::Border);
2279     delete interface;
2280     QTestAccessibility::clearEvents();
2281 }
2282
2283 void tst_QAccessibility::abstractScrollAreaTest()
2284 {
2285     {
2286     QAbstractScrollArea abstractScrollArea;
2287
2288     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
2289     QVERIFY(interface);
2290     QVERIFY(!interface->rect().isValid());
2291     QCOMPARE(interface->childAt(200, 200), -1);
2292
2293     abstractScrollArea.resize(400, 400);
2294     abstractScrollArea.show();
2295 #if defined(Q_OS_UNIX)
2296     QCoreApplication::processEvents();
2297     QTest::qWait(100);
2298 #endif
2299     const QRect globalGeometry = QRect(abstractScrollArea.mapToGlobal(QPoint(0, 0)),
2300                                        abstractScrollArea.size());
2301
2302     // Viewport.
2303     QCOMPARE(interface->childCount(), 1);
2304     QWidget *viewport = abstractScrollArea.viewport();
2305     QVERIFY(viewport);
2306     QVERIFY(verifyChild(viewport, interface, 1, globalGeometry));
2307
2308     // Horizontal scrollBar.
2309     abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2310     QCOMPARE(interface->childCount(), 2);
2311     QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar();
2312     QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget();
2313     QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 2, globalGeometry));
2314
2315     // Horizontal scrollBar widgets.
2316     QLabel *secondLeftLabel = new QLabel(QLatin1String("L2"));
2317     abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft);
2318     QCOMPARE(interface->childCount(), 2);
2319
2320     QLabel *firstLeftLabel = new QLabel(QLatin1String("L1"));
2321     abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft);
2322     QCOMPARE(interface->childCount(), 2);
2323
2324     QLabel *secondRightLabel = new QLabel(QLatin1String("R2"));
2325     abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight);
2326     QCOMPARE(interface->childCount(), 2);
2327
2328     QLabel *firstRightLabel = new QLabel(QLatin1String("R1"));
2329     abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight);
2330     QCOMPARE(interface->childCount(), 2);
2331
2332     // Vertical scrollBar.
2333     abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2334     QCOMPARE(interface->childCount(), 3);
2335     QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar();
2336     QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget();
2337     QVERIFY(verifyChild(verticalScrollBarContainer, interface, 3, globalGeometry));
2338
2339     // Vertical scrollBar widgets.
2340     QLabel *secondTopLabel = new QLabel(QLatin1String("T2"));
2341     abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop);
2342     QCOMPARE(interface->childCount(), 3);
2343
2344     QLabel *firstTopLabel = new QLabel(QLatin1String("T1"));
2345     abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop);
2346     QCOMPARE(interface->childCount(), 3);
2347
2348     QLabel *secondBottomLabel = new QLabel(QLatin1String("B2"));
2349     abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom);
2350     QCOMPARE(interface->childCount(), 3);
2351
2352     QLabel *firstBottomLabel = new QLabel(QLatin1String("B1"));
2353     abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom);
2354     QCOMPARE(interface->childCount(), 3);
2355
2356     // CornerWidget.
2357     abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C")));
2358     QCOMPARE(interface->childCount(), 4);
2359     QWidget *cornerWidget = abstractScrollArea.cornerWidget();
2360     QVERIFY(verifyChild(cornerWidget, interface, 4, globalGeometry));
2361
2362     // Test navigate.
2363     QAccessibleInterface *target = 0;
2364
2365     // viewport -> Up -> NOTHING
2366     const int viewportIndex = indexOfChild(interface, viewport);
2367     QVERIFY(viewportIndex != -1);
2368     QCOMPARE(interface->navigate(QAccessible::Up, viewportIndex, &target), -1);
2369     QVERIFY(!target);
2370
2371     // viewport -> Left -> NOTHING
2372     QCOMPARE(interface->navigate(QAccessible::Left, viewportIndex, &target), -1);
2373     QVERIFY(!target);
2374
2375     // viewport -> Down -> horizontalScrollBarContainer
2376     const int horizontalScrollBarContainerIndex = indexOfChild(interface, horizontalScrollBarContainer);
2377     QVERIFY(horizontalScrollBarContainerIndex != -1);
2378     QCOMPARE(interface->navigate(QAccessible::Down, viewportIndex, &target), 0);
2379     QVERIFY(target);
2380     QCOMPARE(target->object(), static_cast<QObject *>(horizontalScrollBarContainer));
2381     delete target;
2382     target = 0;
2383
2384     // horizontalScrollBarContainer -> Left -> NOTHING
2385     QCOMPARE(interface->navigate(QAccessible::Left, horizontalScrollBarContainerIndex, &target), -1);
2386     QVERIFY(!target);
2387
2388     // horizontalScrollBarContainer -> Down -> NOTHING
2389     QVERIFY(horizontalScrollBarContainerIndex != -1);
2390     QCOMPARE(interface->navigate(QAccessible::Down, horizontalScrollBarContainerIndex, &target), -1);
2391     QVERIFY(!target);
2392
2393     // horizontalScrollBarContainer -> Right -> cornerWidget
2394     const int cornerWidgetIndex = indexOfChild(interface, cornerWidget);
2395     QVERIFY(cornerWidgetIndex != -1);
2396     QCOMPARE(interface->navigate(QAccessible::Right, horizontalScrollBarContainerIndex, &target), 0);
2397     QVERIFY(target);
2398     QCOMPARE(target->object(), static_cast<QObject *>(cornerWidget));
2399     delete target;
2400     target = 0;
2401
2402     // cornerWidget -> Down -> NOTHING
2403     QCOMPARE(interface->navigate(QAccessible::Down, cornerWidgetIndex, &target), -1);
2404     QVERIFY(!target);
2405
2406     // cornerWidget -> Right -> NOTHING
2407     QVERIFY(cornerWidgetIndex != -1);
2408     QCOMPARE(interface->navigate(QAccessible::Right, cornerWidgetIndex, &target), -1);
2409     QVERIFY(!target);
2410
2411     // cornerWidget -> Up ->  verticalScrollBarContainer
2412     const int verticalScrollBarContainerIndex = indexOfChild(interface, verticalScrollBarContainer);
2413     QVERIFY(verticalScrollBarContainerIndex != -1);
2414     QCOMPARE(interface->navigate(QAccessible::Up, cornerWidgetIndex, &target), 0);
2415     QVERIFY(target);
2416     QCOMPARE(target->object(), static_cast<QObject *>(verticalScrollBarContainer));
2417     delete target;
2418     target = 0;
2419
2420     // verticalScrollBarContainer -> Right -> NOTHING
2421     QCOMPARE(interface->navigate(QAccessible::Right, verticalScrollBarContainerIndex, &target), -1);
2422     QVERIFY(!target);
2423
2424     // verticalScrollBarContainer -> Up -> NOTHING
2425     QCOMPARE(interface->navigate(QAccessible::Up, verticalScrollBarContainerIndex, &target), -1);
2426     QVERIFY(!target);
2427
2428     // verticalScrollBarContainer -> Left -> viewport
2429     QCOMPARE(interface->navigate(QAccessible::Left, verticalScrollBarContainerIndex, &target), 0);
2430     QVERIFY(target);
2431     QCOMPARE(target->object(), static_cast<QObject *>(viewport));
2432     delete target;
2433     target = 0;
2434
2435     QCOMPARE(verifyHierarchy(interface), 0);
2436
2437     delete interface;
2438     }
2439
2440     QTestAccessibility::clearEvents();
2441 }
2442
2443 void tst_QAccessibility::scrollAreaTest()
2444 {
2445     {
2446     QScrollArea scrollArea;
2447     scrollArea.show();
2448 #if defined(Q_OS_UNIX)
2449     QCoreApplication::processEvents();
2450     QTest::qWait(100);
2451 #endif
2452     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&scrollArea);
2453     QVERIFY(interface);
2454     QCOMPARE(interface->childCount(), 1); // The viewport.
2455     delete interface;
2456     }
2457     QTestAccessibility::clearEvents();
2458 }
2459
2460 void tst_QAccessibility::listTest()
2461 {
2462     QListWidget *listView = new QListWidget;
2463     listView->addItem("Oslo");
2464     listView->addItem("Berlin");
2465     listView->addItem("Brisbane");
2466     listView->resize(400,400);
2467     listView->show();
2468     QTest::qWait(1); // Need this for indexOfchild to work.
2469     QCoreApplication::processEvents();
2470     QTest::qWait(100);
2471
2472     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(listView);
2473     QCOMPARE(verifyHierarchy(iface), 0);
2474
2475     QCOMPARE((int)iface->role(), (int)QAccessible::List);
2476     QCOMPARE(iface->childCount(), 3);
2477
2478     QAccessibleInterface *child1 = 0;
2479     child1 = iface->child(0);
2480     QVERIFY(child1);
2481     QCOMPARE(iface->indexOfChild(child1), 1);
2482     QCOMPARE(child1->text(QAccessible::Name), QString("Oslo"));
2483     QCOMPARE(child1->role(), QAccessible::ListItem);
2484     delete child1;
2485
2486     QAccessibleInterface *child2 = 0;
2487     child2 = iface->child(1);
2488     QVERIFY(child2);
2489     QCOMPARE(iface->indexOfChild(child2), 2);
2490     QCOMPARE(child2->text(QAccessible::Name), QString("Berlin"));
2491     delete child2;
2492
2493     QAccessibleInterface *child3 = 0;
2494     child3 = iface->child(2);
2495     QVERIFY(child3);
2496     QCOMPARE(iface->indexOfChild(child3), 3);
2497     QCOMPARE(child3->text(QAccessible::Name), QString("Brisbane"));
2498     delete child3;
2499     QTestAccessibility::clearEvents();
2500
2501     // Check for events
2502     QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
2503     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
2504     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
2505     QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
2506     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
2507     QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
2508
2509     listView->addItem("Munich");
2510     QCOMPARE(iface->childCount(), 4);
2511
2512     // table 2
2513     QAccessibleTableInterface *table2 = iface->tableInterface();
2514     QVERIFY(table2);
2515     QCOMPARE(table2->columnCount(), 1);
2516     QCOMPARE(table2->rowCount(), 4);
2517     QAccessibleInterface *cell1;
2518     QVERIFY(cell1 = table2->cellAt(0,0));
2519     QCOMPARE(cell1->text(QAccessible::Name), QString("Oslo"));
2520     QAccessibleInterface *cell4;
2521     QVERIFY(cell4 = table2->cellAt(3,0));
2522     QCOMPARE(cell4->text(QAccessible::Name), QString("Munich"));
2523     QCOMPARE(cell4->role(), QAccessible::ListItem);
2524
2525     QAccessibleTableCellInterface *cellInterface = cell4->tableCellInterface();
2526     QVERIFY(cellInterface);
2527     QCOMPARE(cellInterface->rowIndex(), 3);
2528     QCOMPARE(cellInterface->columnIndex(), 0);
2529     QVERIFY(!(cell4->state() & QAccessible::Expandable));
2530
2531     delete cell4;
2532     delete cell1;
2533     delete iface;
2534     delete listView;
2535     QTestAccessibility::clearEvents();
2536 }
2537
2538 void tst_QAccessibility::treeTest()
2539 {
2540     QTreeWidget *treeView = new QTreeWidget;
2541     treeView->setColumnCount(2);
2542     QTreeWidgetItem *header = new QTreeWidgetItem;
2543     header->setText(0, "Artist");
2544     header->setText(1, "Work");
2545     treeView->setHeaderItem(header);
2546
2547     QTreeWidgetItem *root1 = new QTreeWidgetItem;
2548     root1->setText(0, "Spain");
2549     treeView->addTopLevelItem(root1);
2550
2551     QTreeWidgetItem *item1 = new QTreeWidgetItem;
2552     item1->setText(0, "Picasso");
2553     item1->setText(1, "Guernica");
2554     root1->addChild(item1);
2555
2556     QTreeWidgetItem *item2 = new QTreeWidgetItem;
2557     item2->setText(0, "Tapies");
2558     item2->setText(1, "Ambrosia");
2559     root1->addChild(item2);
2560
2561     QTreeWidgetItem *root2 = new QTreeWidgetItem;
2562     root2->setText(0, "Austria");
2563     treeView->addTopLevelItem(root2);
2564
2565     QTreeWidgetItem *item3 = new QTreeWidgetItem;
2566     item3->setText(0, "Klimt");
2567     item3->setText(1, "The Kiss");
2568     root2->addChild(item3);
2569
2570     treeView->resize(400,400);
2571     treeView->show();
2572
2573     QCoreApplication::processEvents();
2574     QTest::qWait(100);
2575
2576     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(treeView);
2577     QCOMPARE(verifyHierarchy(iface), 0);
2578
2579     QCOMPARE((int)iface->role(), (int)QAccessible::Tree);
2580     // header and 2 rows (the others are not expanded, thus not visible)
2581     QCOMPARE(iface->childCount(), 6);
2582
2583     QAccessibleInterface *header1 = 0;
2584     header1 = iface->child(0);
2585     QVERIFY(header1);
2586     QCOMPARE(iface->indexOfChild(header1), 1);
2587     QCOMPARE(header1->text(QAccessible::Name), QString("Artist"));
2588     QCOMPARE(header1->role(), QAccessible::ColumnHeader);
2589     delete header1;
2590
2591     QAccessibleInterface *child1 = 0;
2592     child1 = iface->child(2);
2593     QVERIFY(child1);
2594     QCOMPARE(iface->indexOfChild(child1), 3);
2595     QCOMPARE(child1->text(QAccessible::Name), QString("Spain"));
2596     QCOMPARE(child1->role(), QAccessible::TreeItem);
2597     QVERIFY(!(child1->state() & QAccessible::Expanded));
2598     delete child1;
2599
2600     QAccessibleInterface *child2 = 0;
2601     child2 = iface->child(4);
2602     QVERIFY(child2);
2603     QCOMPARE(iface->indexOfChild(child2), 5);
2604     QCOMPARE(child2->text(QAccessible::Name), QString("Austria"));
2605     delete child2;
2606
2607     QTestAccessibility::clearEvents();
2608
2609     // table 2
2610     QAccessibleTableInterface *table2 = iface->tableInterface();
2611     QVERIFY(table2);
2612     QCOMPARE(table2->columnCount(), 2);
2613     QCOMPARE(table2->rowCount(), 2);
2614     QAccessibleInterface *cell1;
2615     QVERIFY(cell1 = table2->cellAt(0,0));
2616     QCOMPARE(cell1->text(QAccessible::Name), QString("Spain"));
2617     QAccessibleInterface *cell2;
2618     QVERIFY(cell2 = table2->cellAt(1,0));
2619     QCOMPARE(cell2->text(QAccessible::Name), QString("Austria"));
2620     QCOMPARE(cell2->role(), QAccessible::TreeItem);
2621     QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1);
2622     QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2623     QVERIFY(cell2->state() & QAccessible::Expandable);
2624     QCOMPARE(iface->indexOfChild(cell2), 5);
2625     QVERIFY(!(cell2->state() & QAccessible::Expanded));
2626     QCOMPARE(table2->columnDescription(1), QString("Work"));
2627     delete cell2;
2628     delete cell1;
2629
2630     treeView->expandAll();
2631
2632     // Need this for indexOfchild to work.
2633     QCoreApplication::processEvents();
2634     QTest::qWait(100);
2635
2636     QCOMPARE(table2->columnCount(), 2);
2637     QCOMPARE(table2->rowCount(), 5);
2638     cell1 = table2->cellAt(1,0);
2639     QCOMPARE(cell1->text(QAccessible::Name), QString("Picasso"));
2640     QCOMPARE(iface->indexOfChild(cell1), 5); // 1 based + 2 header + 2 for root item
2641
2642     cell2 = table2->cellAt(4,0);
2643     QCOMPARE(cell2->text(QAccessible::Name), QString("Klimt"));
2644     QCOMPARE(cell2->role(), QAccessible::TreeItem);
2645     QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4);
2646     QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
2647     QVERIFY(!(cell2->state() & QAccessible::Expandable));
2648     QCOMPARE(iface->indexOfChild(cell2), 11);
2649
2650     QCOMPARE(table2->columnDescription(0), QString("Artist"));
2651     QCOMPARE(table2->columnDescription(1), QString("Work"));
2652
2653     delete iface;
2654     QTestAccessibility::clearEvents();
2655 }
2656
2657 void tst_QAccessibility::tableTest()
2658 {
2659     QTableWidget *tableView = new QTableWidget(3, 3);
2660     tableView->setColumnCount(3);
2661     QStringList hHeader;
2662     hHeader << "h1" << "h2" << "h3";
2663     tableView->setHorizontalHeaderLabels(hHeader);
2664
2665     QStringList vHeader;
2666     vHeader << "v1" << "v2" << "v3";
2667     tableView->setVerticalHeaderLabels(vHeader);
2668
2669     for (int i = 0; i<9; ++i) {
2670         QTableWidgetItem *item = new QTableWidgetItem;
2671         item->setText(QString::number(i/3) + QString(".") + QString::number(i%3));
2672         tableView->setItem(i/3, i%3, item);
2673     }
2674
2675     tableView->resize(600,600);
2676     tableView->show();
2677     QTest::qWait(1); // Need this for indexOfchild to work.
2678     QCoreApplication::processEvents();
2679     QTest::qWait(100);
2680
2681     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(tableView);
2682     QCOMPARE(verifyHierarchy(iface), 0);
2683
2684     QCOMPARE((int)iface->role(), (int)QAccessible::Table);
2685     // header and 2 rows (the others are not expanded, thus not visible)
2686     QCOMPARE(iface->childCount(), 9+3+3+1); // cell+headers+topleft button
2687
2688     QAccessibleInterface *cornerButton = iface->child(0);
2689     QVERIFY(cornerButton);
2690     QCOMPARE(iface->indexOfChild(cornerButton), 1);
2691     QCOMPARE(cornerButton->role(), QAccessible::Pane);
2692     delete cornerButton;
2693
2694     QAccessibleInterface *child1 = iface->child(2);
2695     QVERIFY(child1);
2696     QCOMPARE(iface->indexOfChild(child1), 3);
2697     QCOMPARE(child1->text(QAccessible::Name), QString("h2"));
2698     QCOMPARE(child1->role(), QAccessible::ColumnHeader);
2699     QVERIFY(!(child1->state() & QAccessible::Expanded));
2700     delete child1;
2701
2702     QAccessibleInterface *child2 = iface->child(10);
2703     QVERIFY(child2);
2704     QCOMPARE(iface->indexOfChild(child2), 11);
2705     QCOMPARE(child2->text(QAccessible::Name), QString("1.1"));
2706     QAccessibleTableCellInterface *cell2Iface = child2->tableCellInterface();
2707     QCOMPARE(cell2Iface->rowIndex(), 1);
2708     QCOMPARE(cell2Iface->columnIndex(), 1);
2709     delete child2;
2710
2711     QAccessibleInterface *child3 = iface->child(11);
2712     QCOMPARE(iface->indexOfChild(child3), 12);
2713     QCOMPARE(child3->text(QAccessible::Name), QString("1.2"));
2714     delete child3;
2715
2716     QTestAccessibility::clearEvents();
2717
2718     // table 2
2719     QAccessibleTableInterface *table2 = iface->tableInterface();
2720     QVERIFY(table2);
2721     QCOMPARE(table2->columnCount(), 3);
2722     QCOMPARE(table2->rowCount(), 3);
2723     QAccessibleInterface *cell1;
2724     QVERIFY(cell1 = table2->cellAt(0,0));
2725     QCOMPARE(cell1->text(QAccessible::Name), QString("0.0"));
2726     QCOMPARE(iface->indexOfChild(cell1), 6);
2727
2728     QAccessibleInterface *cell2;
2729     QVERIFY(cell2 = table2->cellAt(0,1));
2730     QCOMPARE(cell2->text(QAccessible::Name), QString("0.1"));
2731     QCOMPARE(cell2->role(), QAccessible::Cell);
2732     QCOMPARE(cell2->tableCellInterface()->rowIndex(), 0);
2733     QCOMPARE(cell2->tableCellInterface()->columnIndex(), 1);
2734     QCOMPARE(iface->indexOfChild(cell2), 7);
2735     delete cell2;
2736
2737     QAccessibleInterface *cell3;
2738     QVERIFY(cell3 = table2->cellAt(1,2));
2739     QCOMPARE(cell3->text(QAccessible::Name), QString("1.2"));
2740     QCOMPARE(cell3->role(), QAccessible::Cell);
2741     QCOMPARE(cell3->tableCellInterface()->rowIndex(), 1);
2742     QCOMPARE(cell3->tableCellInterface()->columnIndex(), 2);
2743     QCOMPARE(iface->indexOfChild(cell3), 12);
2744     delete cell3;
2745
2746     QCOMPARE(table2->columnDescription(0), QString("h1"));
2747     QCOMPARE(table2->columnDescription(1), QString("h2"));
2748     QCOMPARE(table2->columnDescription(2), QString("h3"));
2749     QCOMPARE(table2->rowDescription(0), QString("v1"));
2750     QCOMPARE(table2->rowDescription(1), QString("v2"));
2751     QCOMPARE(table2->rowDescription(2), QString("v3"));
2752
2753     delete iface;
2754
2755     delete tableView;
2756
2757     QTestAccessibility::clearEvents();
2758 }
2759
2760 void tst_QAccessibility::calendarWidgetTest()
2761 {
2762 #ifndef QT_NO_CALENDARWIDGET
2763     {
2764     QCalendarWidget calendarWidget;
2765
2766     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&calendarWidget);
2767     QVERIFY(interface);
2768     QCOMPARE(interface->role(), QAccessible::Table);
2769     QVERIFY(!interface->rect().isValid());
2770     QCOMPARE(interface->childAt(200, 200), -1);
2771
2772     calendarWidget.resize(400, 300);
2773     calendarWidget.show();
2774 #if defined(Q_OS_UNIX)
2775     QCoreApplication::processEvents();
2776     QTest::qWait(100);
2777 #endif
2778
2779     // 1 = navigationBar, 2 = view.
2780     QCOMPARE(interface->childCount(), 2);
2781
2782     const QRect globalGeometry = QRect(calendarWidget.mapToGlobal(QPoint(0, 0)),
2783                                        calendarWidget.size());
2784     QCOMPARE(interface->rect(), globalGeometry);
2785
2786     QWidget *navigationBar = 0;
2787     foreach (QObject *child, calendarWidget.children()) {
2788         if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) {
2789             navigationBar = static_cast<QWidget *>(child);
2790             break;
2791         }
2792     }
2793     QVERIFY(navigationBar);
2794     QVERIFY(verifyChild(navigationBar, interface, 1, globalGeometry));
2795
2796     QAbstractItemView *calendarView = 0;
2797     foreach (QObject *child, calendarWidget.children()) {
2798         if (child->objectName() == QLatin1String("qt_calendar_calendarview")) {
2799             calendarView = static_cast<QAbstractItemView *>(child);
2800             break;
2801         }
2802     }
2803     QVERIFY(calendarView);
2804     QVERIFY(verifyChild(calendarView, interface, 2, globalGeometry));
2805
2806     // Hide navigation bar.
2807     calendarWidget.setNavigationBarVisible(false);
2808     QCOMPARE(interface->childCount(), 1);
2809     QVERIFY(!navigationBar->isVisible());
2810
2811     QVERIFY(verifyChild(calendarView, interface, 1, globalGeometry));
2812
2813     // Show navigation bar.
2814     calendarWidget.setNavigationBarVisible(true);
2815     QCOMPARE(interface->childCount(), 2);
2816     QVERIFY(navigationBar->isVisible());
2817
2818     // Navigate to the navigation bar via Child.
2819     QAccessibleInterface *navigationBarInterface = interface->child(0);
2820     QVERIFY(navigationBarInterface);
2821     QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2822     delete navigationBarInterface;
2823     navigationBarInterface = 0;
2824
2825     // Navigate to the view via Child.
2826     QAccessibleInterface *calendarViewInterface = interface->child(1);
2827     QVERIFY(calendarViewInterface);
2828     QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2829     delete calendarViewInterface;
2830     calendarViewInterface = 0;
2831
2832     QVERIFY(!interface->child(-1));
2833
2834     // Navigate from navigation bar -> view (Down).
2835     QCOMPARE(interface->navigate(QAccessible::Down, 1, &calendarViewInterface), 0);
2836     QVERIFY(calendarViewInterface);
2837     QCOMPARE(calendarViewInterface->object(), (QObject*)calendarView);
2838     delete calendarViewInterface;
2839     calendarViewInterface = 0;
2840
2841     // Navigate from view -> navigation bar (Up).
2842     QCOMPARE(interface->navigate(QAccessible::Up, 2, &navigationBarInterface), 0);
2843     QVERIFY(navigationBarInterface);
2844     QCOMPARE(navigationBarInterface->object(), (QObject*)navigationBar);
2845     delete navigationBarInterface;
2846     navigationBarInterface = 0;
2847
2848     }
2849     QTestAccessibility::clearEvents();
2850 #endif // QT_NO_CALENDARWIDGET
2851 }
2852
2853 void tst_QAccessibility::dockWidgetTest()
2854 {
2855 #ifndef QT_NO_DOCKWIDGET
2856     // Set up a proper main window with two dock widgets
2857     QMainWindow *mw = new QMainWindow();
2858     QFrame *central = new QFrame(mw);
2859     mw->setCentralWidget(central);
2860     QMenuBar *mb = new QMenuBar(mw);
2861     mb->addAction(tr("&File"));
2862     mw->setMenuBar(mb);
2863
2864     QDockWidget *dock1 = new QDockWidget(mw);
2865     mw->addDockWidget(Qt::LeftDockWidgetArea, dock1);
2866     QPushButton *pb1 = new QPushButton(tr("Push me"), dock1);
2867     dock1->setWidget(pb1);
2868
2869     QDockWidget *dock2 = new QDockWidget(mw);
2870     mw->addDockWidget(Qt::BottomDockWidgetArea, dock2);
2871     QPushButton *pb2 = new QPushButton(tr("Push me"), dock2);
2872     dock2->setWidget(pb2);
2873
2874     mw->resize(600,400);
2875     mw->show();
2876 #if defined(Q_OS_UNIX)
2877     QCoreApplication::processEvents();
2878     QTest::qWait(100);
2879 #endif
2880
2881     QAccessibleInterface *accMainWindow = QAccessible::queryAccessibleInterface(mw);
2882     // 4 children: menu bar, dock1, dock2, and central widget
2883     QCOMPARE(accMainWindow->childCount(), 4);
2884     QAccessibleInterface *accDock1 = 0;
2885     for (int i = 0; i < 4; ++i) {
2886         accDock1 = accMainWindow->child(i);
2887         if (accMainWindow->role() == QAccessible::Window) {
2888             if (accDock1 && qobject_cast<QDockWidget*>(accDock1->object()) == dock1) {
2889                 break;
2890             } else {
2891                 delete accDock1;
2892             }
2893         }
2894     }
2895     QVERIFY(accDock1);
2896     QCOMPARE(accDock1->role(), QAccessible::Window);
2897
2898     QAccessibleInterface *dock1TitleBar = accDock1->child(0);
2899     QCOMPARE(dock1TitleBar->role(), QAccessible::TitleBar);
2900     QVERIFY(accDock1->rect().contains(dock1TitleBar->rect()));
2901     delete dock1TitleBar;
2902
2903     QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
2904     globalPos.rx()+=5;  //### query style
2905     globalPos.ry()+=5;
2906     int entry = accDock1->childAt(globalPos.x(), globalPos.y());    //###
2907     QCOMPARE(entry, 1);
2908     QAccessibleInterface *accTitleBar = accDock1->child(entry - 1);
2909
2910     QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
2911     QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);
2912     QAccessibleInterface *acc;
2913     acc = accTitleBar->parent();
2914     QVERIFY(acc);
2915     QCOMPARE(acc->role(), QAccessible::Window);
2916
2917
2918     delete accTitleBar;
2919     delete accDock1;
2920     delete pb1;
2921     delete pb2;
2922     delete dock1;
2923     delete dock2;
2924     delete mw;
2925     QTestAccessibility::clearEvents();
2926 #endif // QT_NO_DOCKWIDGET
2927 }
2928
2929 void tst_QAccessibility::comboBoxTest()
2930 {
2931 #if defined(Q_OS_WINCE)
2932     if (!IsValidCEPlatform())
2933         QSKIP("Test skipped on Windows Mobile test hardware");
2934 #endif
2935     { // not editable combobox
2936     QComboBox combo;
2937     combo.addItems(QStringList() << "one" << "two" << "three");
2938     combo.show();
2939     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
2940     QCOMPARE(verifyHierarchy(iface), 0);
2941
2942     QCOMPARE(iface->role(), QAccessible::ComboBox);
2943     QCOMPARE(iface->childCount(), 1);
2944
2945 #ifdef Q_OS_UNIX
2946     QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one"));
2947 #endif
2948     QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one"));
2949     combo.setCurrentIndex(2);
2950 #ifdef Q_OS_UNIX
2951     QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three"));
2952 #endif
2953     QCOMPARE(iface->text(QAccessible::Value), QLatin1String("three"));
2954
2955     QAccessibleInterface *listIface = iface->child(0);
2956     QCOMPARE(listIface->role(), QAccessible::List);
2957     QCOMPARE(listIface->childCount(), 3);
2958
2959     QVERIFY(!combo.view()->isVisible());
2960     QVERIFY(iface->actionInterface());
2961     QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
2962     iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
2963     QVERIFY(combo.view()->isVisible());
2964
2965     delete iface;
2966     }
2967
2968     { // editable combobox
2969     QComboBox editableCombo;
2970     editableCombo.show();
2971     editableCombo.setEditable(true);
2972     editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
2973
2974     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&editableCombo);
2975     QCOMPARE(verifyHierarchy(iface), 0);
2976
2977     QCOMPARE(iface->role(), QAccessible::ComboBox);
2978     QCOMPARE(iface->childCount(), 2);
2979
2980     QAccessibleInterface *listIface = iface->child(0);
2981     QCOMPARE(listIface->role(), QAccessible::List);
2982     QAccessibleInterface *editIface = iface->child(1);
2983     QCOMPARE(editIface->role(), QAccessible::EditableText);
2984
2985     delete listIface;
2986     delete editIface;
2987     delete iface;
2988     }
2989
2990     QTestAccessibility::clearEvents();
2991 }
2992
2993 void tst_QAccessibility::labelTest()
2994 {
2995     QString text = "Hello World";
2996     QLabel *label = new QLabel(text);
2997     label->show();
2998
2999 #if defined(Q_OS_UNIX)
3000     QCoreApplication::processEvents();
3001 #endif
3002     QTest::qWait(100);
3003
3004     QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label);
3005     QVERIFY(acc_label);
3006
3007     QCOMPARE(acc_label->text(QAccessible::Name), text);
3008
3009     delete acc_label;
3010     delete label;
3011     QTestAccessibility::clearEvents();
3012
3013     QPixmap testPixmap(50, 50);
3014     testPixmap.fill();
3015
3016     QLabel imageLabel;
3017     imageLabel.setPixmap(testPixmap);
3018     imageLabel.setToolTip("Test Description");
3019
3020     acc_label = QAccessible::queryAccessibleInterface(&imageLabel);
3021     QVERIFY(acc_label);
3022
3023     QAccessibleImageInterface *imageInterface = acc_label->imageInterface();
3024     QVERIFY(imageInterface);
3025
3026     QCOMPARE(imageInterface->imageSize(), testPixmap.size());
3027     QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
3028     QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
3029
3030     delete acc_label;
3031
3032     QTestAccessibility::clearEvents();
3033 }
3034
3035 void tst_QAccessibility::accelerators()
3036 {
3037     QWidget *window = new QWidget;
3038     QHBoxLayout *lay = new QHBoxLayout(window);
3039     QLabel *label = new QLabel(tr("&Line edit"), window);
3040     QLineEdit *le = new QLineEdit(window);
3041     lay->addWidget(label);
3042     lay->addWidget(le);
3043     label->setBuddy(le);
3044
3045     window->show();
3046
3047     QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
3048     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3049     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("L"));
3050     label->setText(tr("Q &"));
3051     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3052     label->setText(tr("Q &&"));
3053     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3054     label->setText(tr("Q && A"));
3055     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3056     label->setText(tr("Q &&&A"));
3057     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3058     label->setText(tr("Q &&A"));
3059     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QString());
3060
3061 #if !defined(QT_NO_DEBUG) && !defined(Q_WS_MAC)
3062     QTest::ignoreMessage(QtWarningMsg, "QKeySequence::mnemonic: \"Q &A&B\" contains multiple occurrences of '&'");
3063 #endif
3064     label->setText(tr("Q &A&B"));
3065     QCOMPARE(accLineEdit->text(QAccessible::Accelerator), QKeySequence(Qt::ALT).toString(QKeySequence::NativeText) + QLatin1String("A"));
3066
3067 #if defined(Q_OS_UNIX)
3068     QCoreApplication::processEvents();
3069 #endif
3070     QTest::qWait(100);
3071     delete window;
3072     QTestAccessibility::clearEvents();
3073 }
3074
3075 QTEST_MAIN(tst_QAccessibility)
3076 #include "tst_qaccessibility.moc"