Delete src/widgets/platforms/mac
[profile/ivi/qtbase.git] / tests / auto / other / macgui / guitest.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 "guitest.h"
44 #include <QDebug>
45 #include <QWidget>
46 #include <QStack>
47 #include <QTimer>
48 #include <QtTest/QtTest>
49
50 #ifdef Q_OS_MAC
51 #   include <ApplicationServices/ApplicationServices.h>
52 #endif
53
54
55 /*
56     Not really a test, just prints interface info.
57 */
58 class PrintTest : public TestBase
59 {
60 public:
61     bool operator()(QAccessibleInterface *candidate)
62     {
63         qDebug() << "";
64         qDebug() << "Name" << candidate->text(QAccessible::Name);
65         qDebug() << "Pos" <<  candidate->rect();
66         qDebug() << "Number of children" << candidate->childCount();
67         return false;
68     }
69 };
70
71 class NameTest : public TestBase
72 {
73 public:
74     NameTest(const QString &text, QAccessible::Text textType) : text(text), textType(textType) {}
75     QString text;
76     QAccessible::Text textType;
77
78     bool operator()(QAccessibleInterface *candidate)
79     {
80         return (candidate->text(textType) == text);
81     }
82 };
83
84 void WidgetNavigator::printAll(QWidget *widget)
85 {
86     QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(widget);
87     deleteInDestructor(iface);
88     printAll(iface);
89 }
90
91 void WidgetNavigator::printAll(QAccessibleInterface *interface)
92 {
93     PrintTest printTest;
94     recursiveSearch(&printTest, interface);
95 }
96
97 QAccessibleInterface *WidgetNavigator::find(QAccessible::Text textType, const QString &text, QWidget *start)
98 {
99     QAccessibleInterface *const iface = QAccessible::queryAccessibleInterface(start);
100     deleteInDestructor(iface);
101     return find(textType, text, iface);
102 }
103
104 QAccessibleInterface *WidgetNavigator::find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start)
105 {
106     NameTest nameTest(text, textType);
107     return recursiveSearch(&nameTest, start);
108 }
109
110 /*
111     Recursiveley navigates the accessible hiearchy looking for an interface that
112     passsed the Test (meaning it returns true).
113 */
114 QAccessibleInterface *WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface)
115 {
116     QStack<QAccessibleInterface *> todoInterfaces;
117     todoInterfaces.push(iface);
118
119     while (todoInterfaces.isEmpty() == false) {
120         QAccessibleInterface *testInterface = todoInterfaces.pop();
121         
122         if ((*test)(testInterface))
123             return testInterface;
124             
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);
131             }
132         }
133     }
134     return 0;
135 }
136
137 void WidgetNavigator::deleteInDestructor(QAccessibleInterface *interface)
138 {
139     interfaces.insert(interface);
140 }
141
142 QWidget *WidgetNavigator::getWidget(QAccessibleInterface *interface)
143 {
144     return qobject_cast<QWidget *>(interface->object());
145 }
146
147 WidgetNavigator::~WidgetNavigator()
148 {
149     foreach(QAccessibleInterface *interface, interfaces) {
150         delete interface;
151     }
152 }
153
154 ///////////////////////////////////////////////////////////////////////////////
155
156 namespace NativeEvents {
157 #ifdef Q_OS_MAC
158    void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse)
159     {
160         CGPoint position;
161         position.x = globalPos.x();
162         position.y = globalPos.y();
163        
164         const bool updateMousePosition = (updateMouse == UpdatePosition);
165         
166         // Mouse down.
167         CGPostMouseEvent(position, updateMousePosition, 3, 
168                         (buttons & Qt::LeftButton) ? true : false, 
169                         (buttons & Qt::MidButton/* Middlebutton! */) ? true : false, 
170                         (buttons & Qt::RightButton) ? true : false);
171
172         // Mouse up.
173         CGPostMouseEvent(position, updateMousePosition, 3, false, false, false);        
174     }
175 #else
176 # error Oops, NativeEvents::mouseClick() is not implemented on this platform.
177 #endif
178 };
179
180 ///////////////////////////////////////////////////////////////////////////////
181
182 GuiTester::GuiTester()
183 {
184     clearSequence();
185 }
186
187 GuiTester::~GuiTester()
188 {
189     foreach(DelayedAction *action, actions)
190         delete action;
191 }
192
193 bool checkPixel(QColor pixel, QColor expected)
194 {
195     const int allowedDiff = 20;
196
197     return !(qAbs(pixel.red() - expected.red()) > allowedDiff ||
198             qAbs(pixel.green() - expected.green()) > allowedDiff ||
199             qAbs(pixel.blue() - expected.blue()) > allowedDiff);
200 }
201
202 /*
203     Tests that the pixels inside rect in image all have the given color. 
204 */
205 bool GuiTester::isFilled(const QImage image, const QRect &rect, const QColor &color)
206 {
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();
212                 return false;
213             }
214         }
215     return true;
216 }
217
218
219 /*
220     Tests that stuff is painted to the pixels inside rect.
221     This test fails if any lines in the given direction have pixels 
222     of only one color.
223 */
224 bool GuiTester::isContent(const QImage image, const QRect &rect, Directions directions)
225 {
226     if (directions & Horizontal) {
227         for (int y = rect.top(); y <= rect.bottom(); ++y) {
228             QColor currentColor = image.pixel(rect.left(), y);
229             bool fullRun = true;
230             for (int x = rect.left() + 1; x <= rect.right(); ++x) {
231                 if (checkPixel(image.pixel(x, y), currentColor) == false) {
232                     fullRun = false;
233                     break;
234                 }
235             }
236             if (fullRun) {
237 //                qDebug() << "Single-color line at horizontal line " << y  << currentColor;
238                 return false;
239             }
240         }
241         return true;
242     } 
243
244     if (directions & Vertical) {
245        for (int x = rect.left(); x <= rect.right(); ++x) {
246             QRgb currentColor = image.pixel(x, rect.top());
247             bool fullRun = true;
248             for (int y = rect.top() + 1; y <= rect.bottom(); ++y) {
249                 if (checkPixel(image.pixel(x, y), currentColor) == false) {
250                     fullRun = false;
251                     break;
252                 }
253             }
254             if (fullRun) {
255 //                qDebug() << "Single-color line at vertical line" << x << currentColor;
256                 return false;
257             }
258         }
259         return true;
260     }
261     return false; // shut the compiler up.
262 }
263
264 void DelayedAction::run()
265 {
266     if (next)
267         QTimer::singleShot(next->delay, next, SLOT(run()));
268 };
269
270 /*
271     Schedules a mouse click at an interface using a singleShot timer.
272     Only one click can be scheduled at a time.
273 */
274 ClickLaterAction::ClickLaterAction(QAccessibleInterface *interface, Qt::MouseButtons buttons)
275 {
276     this->useInterface = true;
277     this->interface = interface;
278     this->buttons = buttons;
279 }
280
281 /*
282     Schedules a mouse click at a widget using a singleShot timer.
283     Only one click can be scheduled at a time.
284 */
285 ClickLaterAction::ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons)
286 {
287     this->useInterface = false;
288     this->widget  = widget;
289     this->buttons = buttons;
290 }
291
292 void ClickLaterAction::run()
293 {
294     if (useInterface) {
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);
301     }
302     DelayedAction::run();
303 }
304
305 void GuiTester::clickLater(QAccessibleInterface *interface, Qt::MouseButtons buttons, int delay)
306 {
307     clearSequence();
308     addToSequence(new ClickLaterAction(interface, buttons), delay);
309     runSequence();
310 }
311
312 void GuiTester::clickLater(QWidget *widget, Qt::MouseButtons buttons, int delay)
313 {
314     clearSequence();
315     addToSequence(new ClickLaterAction(widget, buttons), delay);
316     runSequence();
317 }
318
319 void GuiTester::clearSequence()
320 {
321     startAction = new DelayedAction();
322     actions.insert(startAction);
323     lastAction = startAction;
324 }
325
326 void GuiTester::addToSequence(DelayedAction *action, int delay)
327 {
328     actions.insert(action);
329     action->delay = delay;
330     lastAction->next = action;
331     lastAction = action;
332 }
333
334 void GuiTester::runSequence()
335 {
336     QTimer::singleShot(0, startAction, SLOT(run()));
337 }
338
339 void GuiTester::exitLoopSlot()
340 {
341     QTestEventLoop::instance().exitLoop();
342 }
343