b2984610a4042b2d19b0a7da8fe956b068f3e622
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick1 / qdeclarativefocusscope / tst_qdeclarativefocusscope.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 #include <qtest.h>
42 #include <QSignalSpy>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QtQuick1/qdeclarativeview.h>
46 #include <QtQuick1/private/qdeclarativerectangle_p.h>
47 #include <QtQuick1/private/qdeclarativetextedit_p.h>
48 #include <QtQuick1/private/qdeclarativetext_p.h>
49 #include <QtQuick1/private/qdeclarativefocusscope_p.h>
50
51 class tst_qdeclarativefocusscope : public QObject
52 {
53     Q_OBJECT
54 public:
55     tst_qdeclarativefocusscope() {}
56
57     template<typename T>
58     T *findItem(QGraphicsObject *parent, const QString &id);
59
60 private slots:
61     void basic();
62     void nested();
63     void noFocus();
64     void textEdit();
65     void forceFocus();
66     void noParentFocus();
67     void signalEmission();
68     void qtBug13380();
69     void forceActiveFocus();
70 };
71
72 /*
73    Find an item with the specified id.
74 */
75 template<typename T>
76 T *tst_qdeclarativefocusscope::findItem(QGraphicsObject *parent, const QString &objectName)
77 {
78     const QMetaObject &mo = T::staticMetaObject;
79     QList<QGraphicsItem *> children = parent->childItems();
80     for (int i = 0; i < children.count(); ++i) {
81         QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(children.at(i)->toGraphicsObject());
82         if (item) {
83             if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
84                 return static_cast<T*>(item);
85             }
86             item = findItem<T>(item, objectName);
87             if (item)
88                 return static_cast<T*>(item);
89         }
90     }
91     return 0;
92 }
93
94 void tst_qdeclarativefocusscope::basic()
95 {
96     QDeclarativeView *view = new QDeclarativeView;
97     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test.qml"));
98
99     QDeclarative1FocusScope *item0 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item0"));
100     QDeclarative1Rectangle *item1 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item1"));
101     QDeclarative1Rectangle *item2 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item2"));
102     QDeclarative1Rectangle *item3 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item3"));
103     QVERIFY(item0 != 0);
104     QVERIFY(item1 != 0);
105     QVERIFY(item2 != 0);
106     QVERIFY(item3 != 0);
107
108     view->show();
109     qApp->setActiveWindow(view);
110
111     QTest::qWaitForWindowShown(view);
112
113     QTRY_VERIFY(view->hasFocus());
114     QVERIFY(view->scene()->hasFocus());
115     QVERIFY(item0->hasActiveFocus() == true);
116     QVERIFY(item1->hasActiveFocus() == true);
117     QVERIFY(item2->hasActiveFocus() == false);
118     QVERIFY(item3->hasActiveFocus() == false);
119
120     QTest::keyClick(view, Qt::Key_Right);
121     QVERIFY(item0->hasActiveFocus() == true);
122     QVERIFY(item1->hasActiveFocus() == false);
123     QVERIFY(item2->hasActiveFocus() == true);
124     QVERIFY(item3->hasActiveFocus() == false);
125
126     QTest::keyClick(view, Qt::Key_Down);
127     QVERIFY(item0->hasActiveFocus() == false);
128     QVERIFY(item1->hasActiveFocus() == false);
129     QVERIFY(item2->hasActiveFocus() == false);
130     QVERIFY(item3->hasActiveFocus() == true);
131
132     delete view;
133 }
134
135 void tst_qdeclarativefocusscope::nested()
136 {
137     QDeclarativeView *view = new QDeclarativeView;
138     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test2.qml"));
139
140     QDeclarative1FocusScope *item1 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item1"));
141     QDeclarative1FocusScope *item2 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item2"));
142     QDeclarative1FocusScope *item3 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item3"));
143     QDeclarative1FocusScope *item4 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item4"));
144     QDeclarative1FocusScope *item5 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item5"));
145     QVERIFY(item1 != 0);
146     QVERIFY(item2 != 0);
147     QVERIFY(item3 != 0);
148     QVERIFY(item4 != 0);
149     QVERIFY(item5 != 0);
150
151     view->show();
152     qApp->setActiveWindow(view);
153
154     QTest::qWaitForWindowShown(view);
155
156     QTRY_VERIFY(view->hasFocus());
157     QVERIFY(view->scene()->hasFocus());
158
159     QVERIFY(item1->hasActiveFocus() == true);
160     QVERIFY(item2->hasActiveFocus() == true);
161     QVERIFY(item3->hasActiveFocus() == true);
162     QVERIFY(item4->hasActiveFocus() == true);
163     QVERIFY(item5->hasActiveFocus() == true);
164     delete view;
165 }
166
167 void tst_qdeclarativefocusscope::noFocus()
168 {
169     QDeclarativeView *view = new QDeclarativeView;
170     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test4.qml"));
171
172     QDeclarative1Rectangle *item0 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item0"));
173     QDeclarative1Rectangle *item1 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item1"));
174     QDeclarative1Rectangle *item2 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item2"));
175     QDeclarative1Rectangle *item3 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item3"));
176     QVERIFY(item0 != 0);
177     QVERIFY(item1 != 0);
178     QVERIFY(item2 != 0);
179     QVERIFY(item3 != 0);
180
181     view->show();
182     qApp->setActiveWindow(view);
183
184     QTest::qWaitForWindowShown(view);
185
186     QTRY_VERIFY(view->hasFocus());
187     QVERIFY(view->scene()->hasFocus());
188     QVERIFY(item0->hasActiveFocus() == false);
189     QVERIFY(item1->hasActiveFocus() == false);
190     QVERIFY(item2->hasActiveFocus() == false);
191     QVERIFY(item3->hasActiveFocus() == false);
192
193     QTest::keyClick(view, Qt::Key_Right);
194     QVERIFY(item0->hasActiveFocus() == false);
195     QVERIFY(item1->hasActiveFocus() == false);
196     QVERIFY(item2->hasActiveFocus() == false);
197     QVERIFY(item3->hasActiveFocus() == false);
198
199     QTest::keyClick(view, Qt::Key_Down);
200     QVERIFY(item0->hasActiveFocus() == false);
201     QVERIFY(item1->hasActiveFocus() == false);
202     QVERIFY(item2->hasActiveFocus() == false);
203     QVERIFY(item3->hasActiveFocus() == false);
204
205     delete view;
206 }
207
208 void tst_qdeclarativefocusscope::textEdit()
209 {
210     QDeclarativeView *view = new QDeclarativeView;
211     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test5.qml"));
212
213     QDeclarative1FocusScope *item0 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item0"));
214     QDeclarative1TextEdit *item1 = findItem<QDeclarative1TextEdit>(view->rootObject(), QLatin1String("item1"));
215     QDeclarative1Rectangle *item2 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item2"));
216     QDeclarative1TextEdit *item3 = findItem<QDeclarative1TextEdit>(view->rootObject(), QLatin1String("item3"));
217     QVERIFY(item0 != 0);
218     QVERIFY(item1 != 0);
219     QVERIFY(item2 != 0);
220     QVERIFY(item3 != 0);
221
222     view->show();
223     qApp->setActiveWindow(view);
224
225     QTest::qWaitForWindowShown(view);
226
227     QTRY_VERIFY(view->hasFocus());
228     QVERIFY(view->scene()->hasFocus());
229     QVERIFY(item0->hasActiveFocus() == true);
230     QVERIFY(item1->hasActiveFocus() == true);
231     QVERIFY(item2->hasActiveFocus() == false);
232     QVERIFY(item3->hasActiveFocus() == false);
233
234     QTest::keyClick(view, Qt::Key_Right);
235     QVERIFY(item0->hasActiveFocus() == true);
236     QVERIFY(item1->hasActiveFocus() == true);
237     QVERIFY(item2->hasActiveFocus() == false);
238     QVERIFY(item3->hasActiveFocus() == false);
239
240     QTest::keyClick(view, Qt::Key_Right);
241     QTest::keyClick(view, Qt::Key_Right);
242     QTest::keyClick(view, Qt::Key_Right);
243     QTest::keyClick(view, Qt::Key_Right);
244     QTest::keyClick(view, Qt::Key_Right);
245     QVERIFY(item0->hasActiveFocus() == true);
246     QVERIFY(item1->hasActiveFocus() == false);
247     QVERIFY(item2->hasActiveFocus() == true);
248     QVERIFY(item3->hasActiveFocus() == false);
249
250     QTest::keyClick(view, Qt::Key_Down);
251     QVERIFY(item0->hasActiveFocus() == false);
252     QVERIFY(item1->hasActiveFocus() == false);
253     QVERIFY(item2->hasActiveFocus() == false);
254     QVERIFY(item3->hasActiveFocus() == true);
255
256     delete view;
257 }
258
259 void tst_qdeclarativefocusscope::forceFocus()
260 {
261     QDeclarativeView *view = new QDeclarativeView;
262     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/forcefocus.qml"));
263
264     QDeclarative1FocusScope *item0 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item0"));
265     QDeclarative1Rectangle *item1 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item1"));
266     QDeclarative1Rectangle *item2 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item2"));
267     QDeclarative1FocusScope *item3 = findItem<QDeclarative1FocusScope>(view->rootObject(), QLatin1String("item3"));
268     QDeclarative1Rectangle *item4 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item4"));
269     QDeclarative1Rectangle *item5 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item5"));
270     QVERIFY(item0 != 0);
271     QVERIFY(item1 != 0);
272     QVERIFY(item2 != 0);
273     QVERIFY(item3 != 0);
274     QVERIFY(item4 != 0);
275     QVERIFY(item5 != 0);
276
277     view->show();
278     qApp->setActiveWindow(view);
279
280     QTest::qWaitForWindowShown(view);
281
282     QTRY_VERIFY(view->hasFocus());
283     QVERIFY(view->scene()->hasFocus());
284     QVERIFY(item0->hasActiveFocus() == true);
285     QVERIFY(item1->hasActiveFocus() == true);
286     QVERIFY(item2->hasActiveFocus() == false);
287     QVERIFY(item3->hasActiveFocus() == false);
288     QVERIFY(item4->hasActiveFocus() == false);
289     QVERIFY(item5->hasActiveFocus() == false);
290
291     QTest::keyClick(view, Qt::Key_4);
292     QVERIFY(item0->hasActiveFocus() == true);
293     QVERIFY(item1->hasActiveFocus() == true);
294     QVERIFY(item2->hasActiveFocus() == false);
295     QVERIFY(item3->hasActiveFocus() == false);
296     QVERIFY(item4->hasActiveFocus() == false);
297     QVERIFY(item5->hasActiveFocus() == false);
298
299     QTest::keyClick(view, Qt::Key_5);
300     QVERIFY(item0->hasActiveFocus() == false);
301     QVERIFY(item1->hasActiveFocus() == false);
302     QVERIFY(item2->hasActiveFocus() == false);
303     QVERIFY(item3->hasActiveFocus() == true);
304     QVERIFY(item4->hasActiveFocus() == false);
305     QVERIFY(item5->hasActiveFocus() == true);
306
307     delete view;
308 }
309
310 void tst_qdeclarativefocusscope::noParentFocus()
311 {
312     QDeclarativeView *view = new QDeclarativeView;
313     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/chain.qml"));
314     QVERIFY(view->rootObject());
315
316     QVERIFY(view->rootObject()->property("focus1") == false);
317     QVERIFY(view->rootObject()->property("focus2") == false);
318     QVERIFY(view->rootObject()->property("focus3") == true);
319     QVERIFY(view->rootObject()->property("focus4") == true);
320     QVERIFY(view->rootObject()->property("focus5") == true);
321
322     delete view;
323 }
324
325 void tst_qdeclarativefocusscope::signalEmission()
326 {
327     QDeclarativeView *view = new QDeclarativeView;
328     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/signalEmission.qml"));
329
330     QDeclarative1Rectangle *item1 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item1"));
331     QDeclarative1Rectangle *item2 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item2"));
332     QDeclarative1Rectangle *item3 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item3"));
333     QDeclarative1Rectangle *item4 = findItem<QDeclarative1Rectangle>(view->rootObject(), QLatin1String("item4"));
334     QVERIFY(item1 != 0);
335     QVERIFY(item2 != 0);
336     QVERIFY(item3 != 0);
337     QVERIFY(item4 != 0);
338
339     view->show();
340     qApp->setActiveWindow(view);
341
342     QTest::qWaitForWindowShown(view);
343
344     QVariant blue(QColor("blue"));
345     QVariant red(QColor("red"));
346
347     QTRY_VERIFY(view->hasFocus());
348     QVERIFY(view->scene()->hasFocus());
349     item1->setFocus(true);
350     QCOMPARE(item1->property("color"), red);
351     QCOMPARE(item2->property("color"), blue);
352     QCOMPARE(item3->property("color"), blue);
353     QCOMPARE(item4->property("color"), blue);
354
355     item2->setFocus(true);
356     QCOMPARE(item1->property("color"), blue);
357     QCOMPARE(item2->property("color"), red);
358     QCOMPARE(item3->property("color"), blue);
359     QCOMPARE(item4->property("color"), blue);
360
361     item3->setFocus(true);
362     QCOMPARE(item1->property("color"), blue);
363     QCOMPARE(item2->property("color"), red);
364     QCOMPARE(item3->property("color"), red);
365     QCOMPARE(item4->property("color"), blue);
366
367     item4->setFocus(true);
368     QCOMPARE(item1->property("color"), blue);
369     QCOMPARE(item2->property("color"), red);
370     QCOMPARE(item3->property("color"), blue);
371     QCOMPARE(item4->property("color"), red);
372
373     item4->setFocus(false);
374     QCOMPARE(item1->property("color"), blue);
375     QCOMPARE(item2->property("color"), red);
376     QCOMPARE(item3->property("color"), blue);
377     QCOMPARE(item4->property("color"), blue);
378
379     delete view;
380 }
381
382 void tst_qdeclarativefocusscope::qtBug13380()
383 {
384     QDeclarativeView *view = new QDeclarativeView;
385     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtBug13380.qml"));
386
387     view->show();
388     QVERIFY(view->rootObject());
389     qApp->setActiveWindow(view);
390
391     QTest::qWaitForWindowShown(view);
392
393     QTRY_VERIFY(view->hasFocus());
394     QVERIFY(view->scene()->hasFocus());
395     QVERIFY(view->rootObject()->property("noFocus").toBool());
396
397     view->rootObject()->setProperty("showRect", true);
398     QVERIFY(view->rootObject()->property("noFocus").toBool());
399
400     delete view;
401 }
402
403 void tst_qdeclarativefocusscope::forceActiveFocus()
404 {
405     QDeclarativeView *view = new QDeclarativeView;
406     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/forceActiveFocus.qml"));
407
408     QGraphicsObject *rootObject = view->rootObject();
409     QVERIFY(rootObject);
410
411     QDeclarativeItem *scope = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope"));
412     QDeclarativeItem *itemA1 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-a1"));
413     QDeclarativeItem *scopeA = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope-a"));
414     QDeclarativeItem *itemA2 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-a2"));
415     QDeclarativeItem *itemB1 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-b1"));
416     QDeclarativeItem *scopeB = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope-b"));
417     QDeclarativeItem *itemB2 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-b2"));
418
419     QVERIFY(scope);
420     QVERIFY(itemA1);
421     QVERIFY(scopeA);
422     QVERIFY(itemA2);
423     QVERIFY(itemB1);
424     QVERIFY(scopeB);
425     QVERIFY(itemB2);
426
427     QSignalSpy rootSpy(rootObject, SIGNAL(activeFocusChanged(bool)));
428     QSignalSpy scopeSpy(scope, SIGNAL(activeFocusChanged(bool)));
429     QSignalSpy scopeASpy(scopeA, SIGNAL(activeFocusChanged(bool)));
430     QSignalSpy scopeBSpy(scopeB, SIGNAL(activeFocusChanged(bool)));
431
432     // First, walk the focus from item-a1 down to item-a2 and back again
433     itemA1->forceActiveFocus();
434     QVERIFY(itemA1->hasActiveFocus());
435     QCOMPARE(rootSpy.count(), 1);
436     QCOMPARE(scopeSpy.count(), 1);
437
438     scopeA->forceActiveFocus();
439     QVERIFY(!itemA1->hasActiveFocus());
440     QVERIFY(scopeA->hasActiveFocus());
441     QCOMPARE(scopeASpy.count(), 1);
442     QCOMPARE(rootSpy.count(), 1);
443     QCOMPARE(scopeSpy.count(), 1);
444
445     itemA2->forceActiveFocus();
446     QVERIFY(!itemA1->hasActiveFocus());
447     QVERIFY(itemA2->hasActiveFocus());
448     QVERIFY(scopeA->hasActiveFocus());
449     QCOMPARE(scopeASpy.count(), 1);
450     QCOMPARE(rootSpy.count(), 1);
451     QCOMPARE(scopeSpy.count(), 1);
452
453     scopeA->forceActiveFocus();
454     QVERIFY(!itemA1->hasActiveFocus());
455     QVERIFY(itemA2->hasActiveFocus());
456     QVERIFY(scopeA->hasActiveFocus());
457     QCOMPARE(scopeASpy.count(), 1);
458     QCOMPARE(rootSpy.count(), 1);
459     QCOMPARE(scopeSpy.count(), 1);
460
461     itemA1->forceActiveFocus();
462     QVERIFY(itemA1->hasActiveFocus());
463     QVERIFY(!scopeA->hasActiveFocus());
464     QVERIFY(!itemA2->hasActiveFocus());
465     QCOMPARE(scopeASpy.count(), 2);
466     QCOMPARE(rootSpy.count(), 1);
467     QCOMPARE(scopeSpy.count(), 1);
468
469     // Then jump back and forth between branch 'a' and 'b'
470     itemB1->forceActiveFocus();
471     QVERIFY(itemB1->hasActiveFocus());
472     QCOMPARE(rootSpy.count(), 1);
473     QCOMPARE(scopeSpy.count(), 1);
474
475     scopeA->forceActiveFocus();
476     QVERIFY(!itemA1->hasActiveFocus());
477     QVERIFY(!itemB1->hasActiveFocus());
478     QVERIFY(scopeA->hasActiveFocus());
479     QCOMPARE(scopeASpy.count(), 3);
480     QCOMPARE(rootSpy.count(), 1);
481     QCOMPARE(scopeSpy.count(), 1);
482
483     scopeB->forceActiveFocus();
484     QVERIFY(!scopeA->hasActiveFocus());
485     QVERIFY(!itemB1->hasActiveFocus());
486     QVERIFY(scopeB->hasActiveFocus());
487     QCOMPARE(scopeASpy.count(), 4);
488     QCOMPARE(scopeBSpy.count(), 1);
489     QCOMPARE(rootSpy.count(), 1);
490     QCOMPARE(scopeSpy.count(), 1);
491
492     itemA2->forceActiveFocus();
493     QVERIFY(!scopeB->hasActiveFocus());
494     QVERIFY(itemA2->hasActiveFocus());
495     QCOMPARE(scopeASpy.count(), 5);
496     QCOMPARE(scopeBSpy.count(), 2);
497     QCOMPARE(rootSpy.count(), 1);
498     QCOMPARE(scopeSpy.count(), 1);
499
500     itemB2->forceActiveFocus();
501     QVERIFY(!itemA2->hasActiveFocus());
502     QVERIFY(itemB2->hasActiveFocus());
503     QCOMPARE(scopeASpy.count(), 6);
504     QCOMPARE(scopeBSpy.count(), 3);
505     QCOMPARE(rootSpy.count(), 1);
506     QCOMPARE(scopeSpy.count(), 1);
507
508     delete view;
509 }
510
511 QTEST_MAIN(tst_qdeclarativefocusscope)
512
513 #include "tst_qdeclarativefocusscope.moc"