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