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