1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
48 #include <QtTest/QtTest>
51 # include <ApplicationServices/ApplicationServices.h>
56 Not really a test, just prints interface info.
58 class PrintTest : public TestBase
61 bool operator()(QAccessibleInterface *candidate)
64 qDebug() << "Name" << candidate->text(QAccessible::Name);
65 qDebug() << "Pos" << candidate->rect();
66 qDebug() << "Number of children" << candidate->childCount();
71 class NameTest : public TestBase
74 NameTest(const QString &text, QAccessible::Text textType) : text(text), textType(textType) {}
76 QAccessible::Text textType;
78 bool operator()(QAccessibleInterface *candidate)
80 return (candidate->text(textType) == text);
84 void WidgetNavigator::printAll(QWidget *widget)
86 QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(widget);
87 deleteInDestructor(iface);
91 void WidgetNavigator::printAll(QAccessibleInterface *interface)
94 recursiveSearch(&printTest, interface);
97 QAccessibleInterface *WidgetNavigator::find(QAccessible::Text textType, const QString &text, QWidget *start)
99 QAccessibleInterface *const iface = QAccessible::queryAccessibleInterface(start);
100 deleteInDestructor(iface);
101 return find(textType, text, iface);
104 QAccessibleInterface *WidgetNavigator::find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start)
106 NameTest nameTest(text, textType);
107 return recursiveSearch(&nameTest, start);
111 Recursiveley navigates the accessible hiearchy looking for an interface that
112 passsed the Test (meaning it returns true).
114 QAccessibleInterface *WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface)
116 QStack<QAccessibleInterface *> todoInterfaces;
117 todoInterfaces.push(iface);
119 while (todoInterfaces.isEmpty() == false) {
120 QAccessibleInterface *testInterface = todoInterfaces.pop();
122 if ((*test)(testInterface))
123 return testInterface;
125 const int numChildren = testInterface->childCount();
126 for (int i = 0; i < numChildren; ++i) {
127 QAccessibleInterface *childInterface = testInterface->child(i);
128 if (childInterface) {
129 todoInterfaces.push(childInterface);
130 deleteInDestructor(childInterface);
137 void WidgetNavigator::deleteInDestructor(QAccessibleInterface *interface)
139 interfaces.insert(interface);
142 QWidget *WidgetNavigator::getWidget(QAccessibleInterface *interface)
144 return qobject_cast<QWidget *>(interface->object());
147 WidgetNavigator::~WidgetNavigator()
149 foreach(QAccessibleInterface *interface, interfaces) {
154 ///////////////////////////////////////////////////////////////////////////////
156 namespace NativeEvents {
158 void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse)
161 position.x = globalPos.x();
162 position.y = globalPos.y();
164 const bool updateMousePosition = (updateMouse == UpdatePosition);
167 CGPostMouseEvent(position, updateMousePosition, 3,
168 (buttons & Qt::LeftButton) ? true : false,
169 (buttons & Qt::MidButton/* Middlebutton! */) ? true : false,
170 (buttons & Qt::RightButton) ? true : false);
173 CGPostMouseEvent(position, updateMousePosition, 3, false, false, false);
176 # error Oops, NativeEvents::mouseClick() is not implemented on this platform.
180 ///////////////////////////////////////////////////////////////////////////////
182 GuiTester::GuiTester()
187 GuiTester::~GuiTester()
189 foreach(DelayedAction *action, actions)
193 bool checkPixel(QColor pixel, QColor expected)
195 const int allowedDiff = 20;
197 return !(qAbs(pixel.red() - expected.red()) > allowedDiff ||
198 qAbs(pixel.green() - expected.green()) > allowedDiff ||
199 qAbs(pixel.blue() - expected.blue()) > allowedDiff);
203 Tests that the pixels inside rect in image all have the given color.
205 bool GuiTester::isFilled(const QImage image, const QRect &rect, const QColor &color)
207 for (int y = rect.top(); y <= rect.bottom(); ++y)
208 for (int x = rect.left(); x <= rect.right(); ++x) {
209 const QColor pixel = image.pixel(x, y);
210 if (checkPixel(pixel, color) == false) {
211 // qDebug()<< "Wrong pixel value at" << x << y << pixel.red() << pixel.green() << pixel.blue();
220 Tests that stuff is painted to the pixels inside rect.
221 This test fails if any lines in the given direction have pixels
224 bool GuiTester::isContent(const QImage image, const QRect &rect, Directions directions)
226 if (directions & Horizontal) {
227 for (int y = rect.top(); y <= rect.bottom(); ++y) {
228 QColor currentColor = image.pixel(rect.left(), y);
230 for (int x = rect.left() + 1; x <= rect.right(); ++x) {
231 if (checkPixel(image.pixel(x, y), currentColor) == false) {
237 // qDebug() << "Single-color line at horizontal line " << y << currentColor;
244 if (directions & Vertical) {
245 for (int x = rect.left(); x <= rect.right(); ++x) {
246 QRgb currentColor = image.pixel(x, rect.top());
248 for (int y = rect.top() + 1; y <= rect.bottom(); ++y) {
249 if (checkPixel(image.pixel(x, y), currentColor) == false) {
255 // qDebug() << "Single-color line at vertical line" << x << currentColor;
261 return false; // shut the compiler up.
264 void DelayedAction::run()
267 QTimer::singleShot(next->delay, next, SLOT(run()));
271 Schedules a mouse click at an interface using a singleShot timer.
272 Only one click can be scheduled at a time.
274 ClickLaterAction::ClickLaterAction(QAccessibleInterface *interface, Qt::MouseButtons buttons)
276 this->useInterface = true;
277 this->interface = interface;
278 this->buttons = buttons;
282 Schedules a mouse click at a widget using a singleShot timer.
283 Only one click can be scheduled at a time.
285 ClickLaterAction::ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons)
287 this->useInterface = false;
288 this->widget = widget;
289 this->buttons = buttons;
292 void ClickLaterAction::run()
295 const QPoint globalCenter = interface->rect().center();
296 NativeEvents::mouseClick(globalCenter, buttons);
297 } else { // use widget
298 const QSize halfSize = widget->size() / 2;
299 const QPoint globalCenter = widget->mapToGlobal(QPoint(halfSize.width(), halfSize.height()));
300 NativeEvents::mouseClick(globalCenter, buttons);
302 DelayedAction::run();
305 void GuiTester::clickLater(QAccessibleInterface *interface, Qt::MouseButtons buttons, int delay)
308 addToSequence(new ClickLaterAction(interface, buttons), delay);
312 void GuiTester::clickLater(QWidget *widget, Qt::MouseButtons buttons, int delay)
315 addToSequence(new ClickLaterAction(widget, buttons), delay);
319 void GuiTester::clearSequence()
321 startAction = new DelayedAction();
322 actions.insert(startAction);
323 lastAction = startAction;
326 void GuiTester::addToSequence(DelayedAction *action, int delay)
328 actions.insert(action);
329 action->delay = delay;
330 lastAction->next = action;
334 void GuiTester::runSequence()
336 QTimer::singleShot(0, startAction, SLOT(run()));
339 void GuiTester::exitLoopSlot()
341 QTestEventLoop::instance().exitLoop();