1 /****************************************************************************
3 ** Copyright (C) 2011 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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QtDeclarative/qdeclarativeview.h>
46 #include <private/qdeclarativerectangle_p.h>
47 #include <private/qdeclarativetextedit_p.h>
48 #include <private/qdeclarativetext_p.h>
49 #include <QtDeclarative/private/qdeclarativefocusscope_p.h>
52 // In Symbian OS test data is located in applications private dir
56 class tst_qdeclarativefocusscope : public QObject
60 tst_qdeclarativefocusscope() {}
63 T *findItem(QGraphicsObject *parent, const QString &id);
72 void signalEmission();
74 void forceActiveFocus();
78 Find an item with the specified id.
81 T *tst_qdeclarativefocusscope::findItem(QGraphicsObject *parent, const QString &objectName)
83 const QMetaObject &mo = T::staticMetaObject;
84 QList<QGraphicsItem *> children = parent->childItems();
85 for (int i = 0; i < children.count(); ++i) {
86 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(children.at(i)->toGraphicsObject());
88 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
89 return static_cast<T*>(item);
91 item = findItem<T>(item, objectName);
93 return static_cast<T*>(item);
99 void tst_qdeclarativefocusscope::basic()
101 QDeclarativeView *view = new QDeclarativeView;
102 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test.qml"));
104 QDeclarativeFocusScope *item0 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item0"));
105 QDeclarativeRectangle *item1 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item1"));
106 QDeclarativeRectangle *item2 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item2"));
107 QDeclarativeRectangle *item3 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item3"));
114 qApp->setActiveWindow(view);
115 qApp->processEvents();
118 // to be safe and avoid failing setFocus with window managers
119 qt_x11_wait_for_window_manager(view);
122 QVERIFY(view->hasFocus());
123 QVERIFY(view->scene()->hasFocus());
124 QVERIFY(item0->hasActiveFocus() == true);
125 QVERIFY(item1->hasActiveFocus() == true);
126 QVERIFY(item2->hasActiveFocus() == false);
127 QVERIFY(item3->hasActiveFocus() == false);
129 QTest::keyClick(view, Qt::Key_Right);
130 QVERIFY(item0->hasActiveFocus() == true);
131 QVERIFY(item1->hasActiveFocus() == false);
132 QVERIFY(item2->hasActiveFocus() == true);
133 QVERIFY(item3->hasActiveFocus() == false);
135 QTest::keyClick(view, Qt::Key_Down);
136 QVERIFY(item0->hasActiveFocus() == false);
137 QVERIFY(item1->hasActiveFocus() == false);
138 QVERIFY(item2->hasActiveFocus() == false);
139 QVERIFY(item3->hasActiveFocus() == true);
144 void tst_qdeclarativefocusscope::nested()
146 QDeclarativeView *view = new QDeclarativeView;
147 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test2.qml"));
149 QDeclarativeFocusScope *item1 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item1"));
150 QDeclarativeFocusScope *item2 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item2"));
151 QDeclarativeFocusScope *item3 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item3"));
152 QDeclarativeFocusScope *item4 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item4"));
153 QDeclarativeFocusScope *item5 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item5"));
161 qApp->setActiveWindow(view);
162 qApp->processEvents();
165 // to be safe and avoid failing setFocus with window managers
166 qt_x11_wait_for_window_manager(view);
169 QVERIFY(view->hasFocus());
170 QVERIFY(view->scene()->hasFocus());
172 QVERIFY(item1->hasActiveFocus() == true);
173 QVERIFY(item2->hasActiveFocus() == true);
174 QVERIFY(item3->hasActiveFocus() == true);
175 QVERIFY(item4->hasActiveFocus() == true);
176 QVERIFY(item5->hasActiveFocus() == true);
180 void tst_qdeclarativefocusscope::noFocus()
182 QDeclarativeView *view = new QDeclarativeView;
183 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test4.qml"));
185 QDeclarativeRectangle *item0 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item0"));
186 QDeclarativeRectangle *item1 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item1"));
187 QDeclarativeRectangle *item2 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item2"));
188 QDeclarativeRectangle *item3 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item3"));
195 qApp->setActiveWindow(view);
196 qApp->processEvents();
199 // to be safe and avoid failing setFocus with window managers
200 qt_x11_wait_for_window_manager(view);
203 QVERIFY(view->hasFocus());
204 QVERIFY(view->scene()->hasFocus());
205 QVERIFY(item0->hasActiveFocus() == false);
206 QVERIFY(item1->hasActiveFocus() == false);
207 QVERIFY(item2->hasActiveFocus() == false);
208 QVERIFY(item3->hasActiveFocus() == false);
210 QTest::keyClick(view, Qt::Key_Right);
211 QVERIFY(item0->hasActiveFocus() == false);
212 QVERIFY(item1->hasActiveFocus() == false);
213 QVERIFY(item2->hasActiveFocus() == false);
214 QVERIFY(item3->hasActiveFocus() == false);
216 QTest::keyClick(view, Qt::Key_Down);
217 QVERIFY(item0->hasActiveFocus() == false);
218 QVERIFY(item1->hasActiveFocus() == false);
219 QVERIFY(item2->hasActiveFocus() == false);
220 QVERIFY(item3->hasActiveFocus() == false);
225 void tst_qdeclarativefocusscope::textEdit()
227 QDeclarativeView *view = new QDeclarativeView;
228 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/test5.qml"));
230 QDeclarativeFocusScope *item0 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item0"));
231 QDeclarativeTextEdit *item1 = findItem<QDeclarativeTextEdit>(view->rootObject(), QLatin1String("item1"));
232 QDeclarativeRectangle *item2 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item2"));
233 QDeclarativeTextEdit *item3 = findItem<QDeclarativeTextEdit>(view->rootObject(), QLatin1String("item3"));
240 qApp->setActiveWindow(view);
241 qApp->processEvents();
244 // to be safe and avoid failing setFocus with window managers
245 qt_x11_wait_for_window_manager(view);
248 QVERIFY(view->hasFocus());
249 QVERIFY(view->scene()->hasFocus());
250 QVERIFY(item0->hasActiveFocus() == true);
251 QVERIFY(item1->hasActiveFocus() == true);
252 QVERIFY(item2->hasActiveFocus() == false);
253 QVERIFY(item3->hasActiveFocus() == false);
255 QTest::keyClick(view, Qt::Key_Right);
256 QVERIFY(item0->hasActiveFocus() == true);
257 QVERIFY(item1->hasActiveFocus() == true);
258 QVERIFY(item2->hasActiveFocus() == false);
259 QVERIFY(item3->hasActiveFocus() == false);
261 QTest::keyClick(view, Qt::Key_Right);
262 QTest::keyClick(view, Qt::Key_Right);
263 QTest::keyClick(view, Qt::Key_Right);
264 QTest::keyClick(view, Qt::Key_Right);
265 QTest::keyClick(view, Qt::Key_Right);
266 QVERIFY(item0->hasActiveFocus() == true);
267 QVERIFY(item1->hasActiveFocus() == false);
268 QVERIFY(item2->hasActiveFocus() == true);
269 QVERIFY(item3->hasActiveFocus() == false);
271 QTest::keyClick(view, Qt::Key_Down);
272 QVERIFY(item0->hasActiveFocus() == false);
273 QVERIFY(item1->hasActiveFocus() == false);
274 QVERIFY(item2->hasActiveFocus() == false);
275 QVERIFY(item3->hasActiveFocus() == true);
280 void tst_qdeclarativefocusscope::forceFocus()
282 QDeclarativeView *view = new QDeclarativeView;
283 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/forcefocus.qml"));
285 QDeclarativeFocusScope *item0 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item0"));
286 QDeclarativeRectangle *item1 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item1"));
287 QDeclarativeRectangle *item2 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item2"));
288 QDeclarativeFocusScope *item3 = findItem<QDeclarativeFocusScope>(view->rootObject(), QLatin1String("item3"));
289 QDeclarativeRectangle *item4 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item4"));
290 QDeclarativeRectangle *item5 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item5"));
299 qApp->setActiveWindow(view);
300 qApp->processEvents();
303 // to be safe and avoid failing setFocus with window managers
304 qt_x11_wait_for_window_manager(view);
307 QVERIFY(view->hasFocus());
308 QVERIFY(view->scene()->hasFocus());
309 QVERIFY(item0->hasActiveFocus() == true);
310 QVERIFY(item1->hasActiveFocus() == true);
311 QVERIFY(item2->hasActiveFocus() == false);
312 QVERIFY(item3->hasActiveFocus() == false);
313 QVERIFY(item4->hasActiveFocus() == false);
314 QVERIFY(item5->hasActiveFocus() == false);
316 QTest::keyClick(view, Qt::Key_4);
317 QVERIFY(item0->hasActiveFocus() == true);
318 QVERIFY(item1->hasActiveFocus() == true);
319 QVERIFY(item2->hasActiveFocus() == false);
320 QVERIFY(item3->hasActiveFocus() == false);
321 QVERIFY(item4->hasActiveFocus() == false);
322 QVERIFY(item5->hasActiveFocus() == false);
324 QTest::keyClick(view, Qt::Key_5);
325 QVERIFY(item0->hasActiveFocus() == false);
326 QVERIFY(item1->hasActiveFocus() == false);
327 QVERIFY(item2->hasActiveFocus() == false);
328 QVERIFY(item3->hasActiveFocus() == true);
329 QVERIFY(item4->hasActiveFocus() == false);
330 QVERIFY(item5->hasActiveFocus() == true);
335 void tst_qdeclarativefocusscope::noParentFocus()
337 QDeclarativeView *view = new QDeclarativeView;
338 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/chain.qml"));
339 QVERIFY(view->rootObject());
341 QVERIFY(view->rootObject()->property("focus1") == false);
342 QVERIFY(view->rootObject()->property("focus2") == false);
343 QVERIFY(view->rootObject()->property("focus3") == true);
344 QVERIFY(view->rootObject()->property("focus4") == true);
345 QVERIFY(view->rootObject()->property("focus5") == true);
350 void tst_qdeclarativefocusscope::signalEmission()
352 QDeclarativeView *view = new QDeclarativeView;
353 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/signalEmission.qml"));
355 QDeclarativeRectangle *item1 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item1"));
356 QDeclarativeRectangle *item2 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item2"));
357 QDeclarativeRectangle *item3 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item3"));
358 QDeclarativeRectangle *item4 = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("item4"));
365 qApp->setActiveWindow(view);
366 qApp->processEvents();
369 // to be safe and avoid failing setFocus with window managers
370 qt_x11_wait_for_window_manager(view);
373 QVariant blue(QColor("blue"));
374 QVariant red(QColor("red"));
376 QVERIFY(view->hasFocus());
377 QVERIFY(view->scene()->hasFocus());
378 item1->setFocus(true);
379 QCOMPARE(item1->property("color"), red);
380 QCOMPARE(item2->property("color"), blue);
381 QCOMPARE(item3->property("color"), blue);
382 QCOMPARE(item4->property("color"), blue);
384 item2->setFocus(true);
385 QCOMPARE(item1->property("color"), blue);
386 QCOMPARE(item2->property("color"), red);
387 QCOMPARE(item3->property("color"), blue);
388 QCOMPARE(item4->property("color"), blue);
390 item3->setFocus(true);
391 QCOMPARE(item1->property("color"), blue);
392 QCOMPARE(item2->property("color"), red);
393 QCOMPARE(item3->property("color"), red);
394 QCOMPARE(item4->property("color"), blue);
396 item4->setFocus(true);
397 QCOMPARE(item1->property("color"), blue);
398 QCOMPARE(item2->property("color"), red);
399 QCOMPARE(item3->property("color"), blue);
400 QCOMPARE(item4->property("color"), red);
402 item4->setFocus(false);
403 QCOMPARE(item1->property("color"), blue);
404 QCOMPARE(item2->property("color"), red);
405 QCOMPARE(item3->property("color"), blue);
406 QCOMPARE(item4->property("color"), blue);
411 void tst_qdeclarativefocusscope::qtBug13380()
413 QDeclarativeView *view = new QDeclarativeView;
414 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtBug13380.qml"));
417 QVERIFY(view->rootObject());
418 qApp->setActiveWindow(view);
419 qApp->processEvents();
422 // to be safe and avoid failing setFocus with window managers
423 qt_x11_wait_for_window_manager(view);
426 QVERIFY(view->hasFocus());
427 QVERIFY(view->scene()->hasFocus());
428 QVERIFY(view->rootObject()->property("noFocus").toBool());
430 view->rootObject()->setProperty("showRect", true);
431 QVERIFY(view->rootObject()->property("noFocus").toBool());
436 void tst_qdeclarativefocusscope::forceActiveFocus()
438 QDeclarativeView *view = new QDeclarativeView;
439 view->setSource(QUrl::fromLocalFile(SRCDIR "/data/forceActiveFocus.qml"));
441 QGraphicsObject *rootObject = view->rootObject();
444 QDeclarativeItem *scope = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope"));
445 QDeclarativeItem *itemA1 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-a1"));
446 QDeclarativeItem *scopeA = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope-a"));
447 QDeclarativeItem *itemA2 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-a2"));
448 QDeclarativeItem *itemB1 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-b1"));
449 QDeclarativeItem *scopeB = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope-b"));
450 QDeclarativeItem *itemB2 = findItem<QDeclarativeItem>(rootObject, QLatin1String("item-b2"));
460 QSignalSpy rootSpy(rootObject, SIGNAL(activeFocusChanged(bool)));
461 QSignalSpy scopeSpy(scope, SIGNAL(activeFocusChanged(bool)));
462 QSignalSpy scopeASpy(scopeA, SIGNAL(activeFocusChanged(bool)));
463 QSignalSpy scopeBSpy(scopeB, SIGNAL(activeFocusChanged(bool)));
465 // First, walk the focus from item-a1 down to item-a2 and back again
466 itemA1->forceActiveFocus();
467 QVERIFY(itemA1->hasActiveFocus());
468 QCOMPARE(rootSpy.count(), 1);
469 QCOMPARE(scopeSpy.count(), 1);
471 scopeA->forceActiveFocus();
472 QVERIFY(!itemA1->hasActiveFocus());
473 QVERIFY(scopeA->hasActiveFocus());
474 QCOMPARE(scopeASpy.count(), 1);
475 QCOMPARE(rootSpy.count(), 1);
476 QCOMPARE(scopeSpy.count(), 1);
478 itemA2->forceActiveFocus();
479 QVERIFY(!itemA1->hasActiveFocus());
480 QVERIFY(itemA2->hasActiveFocus());
481 QVERIFY(scopeA->hasActiveFocus());
482 QCOMPARE(scopeASpy.count(), 1);
483 QCOMPARE(rootSpy.count(), 1);
484 QCOMPARE(scopeSpy.count(), 1);
486 scopeA->forceActiveFocus();
487 QVERIFY(!itemA1->hasActiveFocus());
488 QVERIFY(itemA2->hasActiveFocus());
489 QVERIFY(scopeA->hasActiveFocus());
490 QCOMPARE(scopeASpy.count(), 1);
491 QCOMPARE(rootSpy.count(), 1);
492 QCOMPARE(scopeSpy.count(), 1);
494 itemA1->forceActiveFocus();
495 QVERIFY(itemA1->hasActiveFocus());
496 QVERIFY(!scopeA->hasActiveFocus());
497 QVERIFY(!itemA2->hasActiveFocus());
498 QCOMPARE(scopeASpy.count(), 2);
499 QCOMPARE(rootSpy.count(), 1);
500 QCOMPARE(scopeSpy.count(), 1);
502 // Then jump back and forth between branch 'a' and 'b'
503 itemB1->forceActiveFocus();
504 QVERIFY(itemB1->hasActiveFocus());
505 QCOMPARE(rootSpy.count(), 1);
506 QCOMPARE(scopeSpy.count(), 1);
508 scopeA->forceActiveFocus();
509 QVERIFY(!itemA1->hasActiveFocus());
510 QVERIFY(!itemB1->hasActiveFocus());
511 QVERIFY(scopeA->hasActiveFocus());
512 QCOMPARE(scopeASpy.count(), 3);
513 QCOMPARE(rootSpy.count(), 1);
514 QCOMPARE(scopeSpy.count(), 1);
516 scopeB->forceActiveFocus();
517 QVERIFY(!scopeA->hasActiveFocus());
518 QVERIFY(!itemB1->hasActiveFocus());
519 QVERIFY(scopeB->hasActiveFocus());
520 QCOMPARE(scopeASpy.count(), 4);
521 QCOMPARE(scopeBSpy.count(), 1);
522 QCOMPARE(rootSpy.count(), 1);
523 QCOMPARE(scopeSpy.count(), 1);
525 itemA2->forceActiveFocus();
526 QVERIFY(!scopeB->hasActiveFocus());
527 QVERIFY(itemA2->hasActiveFocus());
528 QCOMPARE(scopeASpy.count(), 5);
529 QCOMPARE(scopeBSpy.count(), 2);
530 QCOMPARE(rootSpy.count(), 1);
531 QCOMPARE(scopeSpy.count(), 1);
533 itemB2->forceActiveFocus();
534 QVERIFY(!itemA2->hasActiveFocus());
535 QVERIFY(itemB2->hasActiveFocus());
536 QCOMPARE(scopeASpy.count(), 6);
537 QCOMPARE(scopeBSpy.count(), 3);
538 QCOMPARE(rootSpy.count(), 1);
539 QCOMPARE(scopeSpy.count(), 1);
544 QTEST_MAIN(tst_qdeclarativefocusscope)
546 #include "tst_qdeclarativefocusscope.moc"