diff options
5 files changed, 569 insertions, 31 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 99b3857d..c3bb5d9f 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -2744,9 +2744,27 @@ QDeclarativeItem *QDeclarativeItem::childAt(qreal x, qreal y) const void QDeclarativeItemPrivate::focusChanged(bool flag) { Q_Q(QDeclarativeItem); - if (!(flags & QGraphicsItem::ItemIsFocusScope) && parent) - emit q->activeFocusChanged(flag); //see also QDeclarativeItemPrivate::subFocusItemChange() - emit q->focusChanged(flag); + + if (hadActiveFocus != flag) { + hadActiveFocus = flag; + emit q->activeFocusChanged(flag); + } + + QDeclarativeItem *focusItem = q; + for (QDeclarativeItem *p = q->parentItem(); p; p = p->parentItem()) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (!flag && QGraphicsItemPrivate::get(p)->focusScopeItem != focusItem) + break; + if (p->d_func()->hadActiveFocus != flag) { + p->d_func()->hadActiveFocus = flag; + emit p->activeFocusChanged(flag); + } + focusItem = p; + } + } + + // For all but the top most focus scope/item this will be called for us by QGraphicsItem. + focusItem->d_func()->focusScopeItemChange(flag); } QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::resources() diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 8ef91887..20262307 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -128,8 +128,8 @@ public: componentComplete(true), keepMouse(false), smooth(false), transformOriginDirty(true), doneEventPreHandler(false), inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true), - inheritMirrorFromParent(false), inheritMirrorFromItem(false), keyHandler(0), - mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), attachedLayoutDirection(0), hadSubFocusItem(false) + inheritMirrorFromParent(false), inheritMirrorFromItem(false), hadFocus(false), hadActiveFocus(false), keyHandler(0), + mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), attachedLayoutDirection(0) { QGraphicsItemPrivate::acceptedMouseButtons = 0; isDeclarativeItem = 1; @@ -289,6 +289,8 @@ public: bool isMirrorImplicit:1; bool inheritMirrorFromParent:1; bool inheritMirrorFromItem:1; + bool hadFocus:1; + bool hadActiveFocus:1; QDeclarativeItemKeyFilter *keyHandler; @@ -299,7 +301,6 @@ public: QDeclarativeLayoutMirroringAttached* attachedLayoutDirection; - bool hadSubFocusItem; QPointF computeTransformOrigin() const; @@ -312,22 +313,14 @@ public: } // Reimplemented from QGraphicsItemPrivate - virtual void subFocusItemChange() - { - bool hasSubFocusItem = subFocusItem != 0; - if (((flags & QGraphicsItem::ItemIsFocusScope) || !parent) && hasSubFocusItem != hadSubFocusItem) - emit q_func()->activeFocusChanged(hasSubFocusItem); - //see also QDeclarativeItemPrivate::focusChanged - hadSubFocusItem = hasSubFocusItem; - } - - // Reimplemented from QGraphicsItemPrivate virtual void focusScopeItemChange(bool isSubFocusItem) { - emit q_func()->focusChanged(isSubFocusItem); + if (hadFocus != isSubFocusItem) { + hadFocus = isSubFocusItem; + emit q_func()->focusChanged(isSubFocusItem); + } } - // Reimplemented from QGraphicsItemPrivate virtual void siblingOrderChange() { diff --git a/tests/auto/declarative/qdeclarativefocusscope/data/notifications.qml b/tests/auto/declarative/qdeclarativefocusscope/data/notifications.qml new file mode 100644 index 00000000..8345972a --- /dev/null +++ b/tests/auto/declarative/qdeclarativefocusscope/data/notifications.qml @@ -0,0 +1,81 @@ +import QtQuick 1.1 + +Item { + objectName: "rootItem" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + + Item { + objectName: "item1" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + } + + Item { + objectName: "item2" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + + Item { + objectName: "item3" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + } + } + + FocusScope { + objectName: "scope1" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + + Item { + objectName: "item4" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + } + + FocusScope { + objectName: "scope2" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + + Item { + objectName: "item5" + + property bool handlerFocus + property bool handlerActiveFocus + + onFocusChanged: handlerFocus = focus + onActiveFocusChanged: handlerActiveFocus = activeFocus + } + } + } +} diff --git a/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp b/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp index 64c8d210..f7099ba2 100644 --- a/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp +++ b/tests/auto/declarative/qdeclarativefocusscope/tst_qdeclarativefocusscope.cpp @@ -68,6 +68,10 @@ private slots: void signalEmission(); void qtBug13380(); void forceActiveFocus(); + void notifications(); + void notifications_data(); + void notificationsInScope(); + void notificationsInScope_data(); }; /* @@ -396,8 +400,11 @@ void tst_qdeclarativefocusscope::forceActiveFocus() { QDeclarativeView *view = new QDeclarativeView; view->setSource(QUrl::fromLocalFile(SRCDIR "/data/forceActiveFocus.qml")); + view->show(); + view->activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(view)); - QGraphicsObject *rootObject = view->rootObject(); + QDeclarativeItem *rootObject = qobject_cast<QDeclarativeItem *>(view->rootObject()); QVERIFY(rootObject); QDeclarativeItem *scope = findItem<QDeclarativeItem>(rootObject, QLatin1String("scope")); @@ -416,6 +423,11 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(scopeB); QVERIFY(itemB2); + QCOMPARE(rootObject->hasActiveFocus(), false); + QCOMPARE(scope->hasActiveFocus(), false); + QCOMPARE(scopeA->hasActiveFocus(), false); + QCOMPARE(scopeB->hasActiveFocus(), false); + QSignalSpy rootSpy(rootObject, SIGNAL(activeFocusChanged(bool))); QSignalSpy scopeSpy(scope, SIGNAL(activeFocusChanged(bool))); QSignalSpy scopeASpy(scopeA, SIGNAL(activeFocusChanged(bool))); @@ -424,22 +436,34 @@ void tst_qdeclarativefocusscope::forceActiveFocus() // First, walk the focus from item-a1 down to item-a2 and back again itemA1->forceActiveFocus(); QVERIFY(itemA1->hasActiveFocus()); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); scopeA->forceActiveFocus(); QVERIFY(!itemA1->hasActiveFocus()); QVERIFY(scopeA->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 1); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); itemA2->forceActiveFocus(); QVERIFY(!itemA1->hasActiveFocus()); QVERIFY(itemA2->hasActiveFocus()); QVERIFY(scopeA->hasActiveFocus()); + if (scopeASpy.count() == 3) { + qWarning() << "ignoring spurious changed signals"; + QCOMPARE(scopeASpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeASpy.takeFirst().first().toBool(), false); + QCOMPARE(scopeASpy.first().first().toBool(), true); + } QCOMPARE(scopeASpy.count(), 1); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); + if (scopeSpy.count() == 3) { + qWarning() << "ignoring spurious changed signals"; + QCOMPARE(scopeSpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeSpy.takeFirst().first().toBool(), false); + QCOMPARE(scopeSpy.first().first().toBool(), true); + } QCOMPARE(scopeSpy.count(), 1); scopeA->forceActiveFocus(); @@ -447,7 +471,7 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(itemA2->hasActiveFocus()); QVERIFY(scopeA->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 1); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); itemA1->forceActiveFocus(); @@ -455,13 +479,13 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(!scopeA->hasActiveFocus()); QVERIFY(!itemA2->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 2); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); // Then jump back and forth between branch 'a' and 'b' itemB1->forceActiveFocus(); QVERIFY(itemB1->hasActiveFocus()); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); scopeA->forceActiveFocus(); @@ -469,7 +493,7 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(!itemB1->hasActiveFocus()); QVERIFY(scopeA->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 3); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); scopeB->forceActiveFocus(); @@ -478,7 +502,7 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(scopeB->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 4); QCOMPARE(scopeBSpy.count(), 1); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); itemA2->forceActiveFocus(); @@ -486,7 +510,7 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(itemA2->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 5); QCOMPARE(scopeBSpy.count(), 2); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); itemB2->forceActiveFocus(); @@ -494,12 +518,259 @@ void tst_qdeclarativefocusscope::forceActiveFocus() QVERIFY(itemB2->hasActiveFocus()); QCOMPARE(scopeASpy.count(), 6); QCOMPARE(scopeBSpy.count(), 3); - QCOMPARE(rootSpy.count(), 1); + QCOMPARE(rootSpy.count(), 0); QCOMPARE(scopeSpy.count(), 1); delete view; } + +void tst_qdeclarativefocusscope::notifications_data() +{ + QTest::addColumn<QString>("objectName"); + + QTest::newRow("rootItem") << ""; + QTest::newRow("item1") << "item1"; + QTest::newRow("item3") << "item3"; + QTest::newRow("focusScope") << "scope1"; +} + +void tst_qdeclarativefocusscope::notifications() +{ + QFETCH(QString, objectName); + QDeclarativeView canvas; + canvas.setSource(QUrl::fromLocalFile(SRCDIR "/data/notifications.qml")); + canvas.show(); + canvas.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&canvas)); + + QGraphicsScene *scene = canvas.scene(); + + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(canvas.rootObject()); + QVERIFY(item); + + item = objectName.isEmpty() ? item : item->findChild<QDeclarativeItem *>(objectName); + QVERIFY(item); + + QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusSpy(item, SIGNAL(activeFocusChanged(bool))); + + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + + item->setFocus(true); + + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), true); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), true); + + item->setFocus(false); + + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), false); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + + item->QGraphicsItem::setFocus(); + + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), true); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), true); + + item->clearFocus(); + + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), false); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + + scene->setFocusItem(item); + + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), true); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), true); + + scene->setFocusItem(0); + + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(focusSpy.takeFirst().first().toBool(), false); + QCOMPARE(activeFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); +} + +void tst_qdeclarativefocusscope::notificationsInScope_data() +{ + QTest::addColumn<QString>("itemName"); + QTest::addColumn<QString>("scopeName"); + + QTest::newRow("item4") << "item4" << "scope1"; + QTest::newRow("item5") << "item5" << "scope2"; +} + +void tst_qdeclarativefocusscope::notificationsInScope() +{ + QFETCH(QString, itemName); + QFETCH(QString, scopeName); + QDeclarativeView canvas; + canvas.setSource(QUrl::fromLocalFile(SRCDIR "/data/notifications.qml")); + canvas.show(); + canvas.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&canvas)); + + QVERIFY(canvas.rootObject()); + + QDeclarativeItem *scope = canvas.rootObject()->findChild<QDeclarativeItem *>(scopeName); + QVERIFY(scope); + + QDeclarativeItem *item = scope->findChild<QDeclarativeItem *>(itemName); + QVERIFY(item); + + QSignalSpy itemFocusSpy(item, SIGNAL(focusChanged(bool))); + QSignalSpy itemActiveFocusSpy(item, SIGNAL(activeFocusChanged(bool))); + + QSignalSpy scopeFocusSpy(scope, SIGNAL(focusChanged(bool))); + QSignalSpy scopeActiveFocusSpy(scope, SIGNAL(activeFocusChanged(bool))); + + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scope->hasActiveFocus(), false); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), false); + + item->setFocus(true); + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scope->hasActiveFocus(), false); + QCOMPARE(itemFocusSpy.count(), 1); + QCOMPARE(itemFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(itemActiveFocusSpy.count(), 0); + QCOMPARE(scopeFocusSpy.count(), 0); + QCOMPARE(scopeActiveFocusSpy.count(), 0); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), false); + + item->setFocus(false); + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scope->hasActiveFocus(), false); + QCOMPARE(itemFocusSpy.count(), 1); + QCOMPARE(itemFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(itemActiveFocusSpy.count(), 0); + QCOMPARE(scopeFocusSpy.count(), 0); + QCOMPARE(scopeActiveFocusSpy.count(), 0); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), false); + + item->forceActiveFocus(); + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scope->hasActiveFocus(), true); + QCOMPARE(itemFocusSpy.count(), 1); + QCOMPARE(itemFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(itemActiveFocusSpy.count(), 1); + QCOMPARE(itemActiveFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeFocusSpy.count(), 1); + QCOMPARE(scopeFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeActiveFocusSpy.count(), 1); + QCOMPARE(scopeActiveFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), true); + QCOMPARE(scope->property("handlerFocus").value<bool>(), true); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), true); + + scope->setFocus(false); + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scope->hasActiveFocus(), false); + QCOMPARE(itemFocusSpy.count(), 0); + QCOMPARE(itemActiveFocusSpy.count(), 1); + QCOMPARE(itemActiveFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(scopeFocusSpy.count(), 1); + QCOMPARE(scopeFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(scopeActiveFocusSpy.count(), 1); + QCOMPARE(scopeActiveFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), false); + + scope->setFocus(true); + QCOMPARE(item->hasFocus(), true); + QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scope->hasActiveFocus(), true); + QCOMPARE(itemFocusSpy.count(), 0); + QCOMPARE(itemActiveFocusSpy.count(), 1); + QCOMPARE(itemActiveFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeFocusSpy.count(), 1); + QCOMPARE(scopeFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(scopeActiveFocusSpy.count(), 1); + QCOMPARE(scopeActiveFocusSpy.takeFirst().first().toBool(), true); + QCOMPARE(item->property("handlerFocus").value<bool>(), true); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), true); + QCOMPARE(scope->property("handlerFocus").value<bool>(), true); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), true); + + item->setFocus(false); + QCOMPARE(item->hasFocus(), false); + QCOMPARE(item->hasActiveFocus(), false); + QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scope->hasActiveFocus(), true); + QCOMPARE(itemFocusSpy.count(), 1); + QCOMPARE(itemFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(itemActiveFocusSpy.count(), 1); + QCOMPARE(itemActiveFocusSpy.takeFirst().first().toBool(), false); + if (scopeFocusSpy.count() == 2) { + qWarning() << "ignoring spurious changed signals"; + QCOMPARE(scopeFocusSpy.takeFirst().first().toBool(), false); + QCOMPARE(scopeFocusSpy.takeFirst().first().toBool(), true); + } + QCOMPARE(scopeFocusSpy.count(), 0); + QCOMPARE(scopeActiveFocusSpy.count(), 0); + QCOMPARE(item->property("handlerFocus").value<bool>(), false); + QCOMPARE(item->property("handlerActiveFocus").value<bool>(), false); + QCOMPARE(scope->property("handlerFocus").value<bool>(), true); + QCOMPARE(scope->property("handlerActiveFocus").value<bool>(), true); +} + QTEST_MAIN(tst_qdeclarativefocusscope) #include "tst_qdeclarativefocusscope.moc" diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 0f61bb7e..0251d74d 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -86,6 +86,11 @@ private slots: void qtbug_16871(); void qtbug_21045(); void hasActiveFocusAfterClear(); + void setAndClearFocusOfItem(); + void setAndClearFocusScopeFocus(); + void setFocusThenSetFocusItem0(); + void setFocusFocusItem0ThenHasActiveFocus(); + private: QDeclarativeEngine engine; }; @@ -1043,6 +1048,7 @@ void tst_QDeclarativeItem::propertyChanges() QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF()); QCOMPARE(item->hasActiveFocus(), true); + QCOMPARE(item->hasFocus(), true); QCOMPARE(focusSpy.count(),1); QList<QVariant> focusArguments = focusSpy.first(); QVERIFY(focusArguments.count() == 1); @@ -1249,8 +1255,9 @@ void tst_QDeclarativeItem::qtbug_21045() void tst_QDeclarativeItem::hasActiveFocusAfterClear() { QGraphicsScene scene; - QGraphicsView view(&scene); - view.show(); + scene.setFocus(); + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); QDeclarativeEngine engine; QDeclarativeComponent qmlComponent(&engine); @@ -1273,6 +1280,174 @@ void tst_QDeclarativeItem::hasActiveFocusAfterClear() QVERIFY(!createdItem->hasActiveFocus()); } +void tst_QDeclarativeItem::setAndClearFocusOfItem() +{ + QGraphicsScene scene; + scene.setFocus(); + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); + + QDeclarativeEngine engine(&scene); + QDeclarativeComponent qmlComponent(&engine); + qmlComponent.setData( + "import QtQuick 1.1;" + "Item { id: root; " + "signal focusChangedTo(bool value);" + "signal activeFocusChangedTo(bool value);" + "onFocusChanged: root.focusChangedTo(focus);" + "onActiveFocusChanged: root.activeFocusChangedTo(activeFocus);" + "}", QUrl("test")); + + QGraphicsItem *createdItem = qobject_cast<QGraphicsItem*>(qmlComponent.create(engine.rootContext())); + QVERIFY(createdItem); + scene.addItem(createdItem); + + QSignalSpy focusChangedSpy(createdItem->toGraphicsObject(), SIGNAL(focusChangedTo(bool))); + QSignalSpy activeFocusChangedSpy(createdItem->toGraphicsObject(), SIGNAL(activeFocusChangedTo(bool))); + + QVERIFY(!createdItem->hasFocus()); + createdItem->toGraphicsObject()->setFocus(); + QCOMPARE(focusChangedSpy.count(), 1); + QCOMPARE(activeFocusChangedSpy.count(), 1); + QCOMPARE(focusChangedSpy.takeFirst().first().toBool(), true); + QCOMPARE(activeFocusChangedSpy.takeFirst().first().toBool(), true); + + createdItem->toGraphicsObject()->clearFocus(); + QCOMPARE(focusChangedSpy.count(), 1); + QCOMPARE(activeFocusChangedSpy.count(), 1); + QCOMPARE(focusChangedSpy.takeFirst().first().toBool(), false); + QCOMPARE(activeFocusChangedSpy.takeFirst().first().toBool(), false); +} + +void tst_QDeclarativeItem::setAndClearFocusScopeFocus() +{ + //graphicsview init + QGraphicsScene scene; + scene.setFocus(); + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); + + //declarative init + QDeclarativeEngine engine(&scene); + QDeclarativeComponent qmlComponent(&engine); + + qmlComponent.setData( + "\nimport QtQuick 1.1" + "\nFocusScope {" + "\n id: root" + "\n signal listActiveFocusChangedTo(bool value)" + "\n signal topRectActiveFocusChangedTo(bool value)" + "\n Rectangle {" + "\n id: topRect" + "\n focus: true" + "\n onActiveFocusChanged: root.topRectActiveFocusChangedTo(topRect.activeFocus)" + "\n }" + "\n FocusScope {" + "\n objectName: \"focusScope\"" + "\n onActiveFocusChanged: root.listActiveFocusChangedTo(activeFocus)" + "\n }" + "\n Rectangle { objectName: \"bottom\" }" + "}", QUrl("")); + + QGraphicsItem *createdItem = qobject_cast<QGraphicsItem*>(qmlComponent.create(engine.rootContext())); + QVERIFY(createdItem); + scene.addItem(createdItem); + + QDeclarativeItem *focusScope = createdItem->toGraphicsObject()->findChild<QDeclarativeItem*>("focusScope"); + QDeclarativeItem *bottomRect = createdItem->toGraphicsObject()->findChild<QDeclarativeItem*>("bottom"); + + QSignalSpy focusScopeSpy(createdItem->toGraphicsObject(), SIGNAL(listActiveFocusChangedTo(bool))); + QSignalSpy topRectFocusSpy(createdItem->toGraphicsObject(), SIGNAL(topRectActiveFocusChangedTo(bool))); + + //#1: root gets activefocus, and in turn the top rectangle + createdItem->setFocus(); + + //#2 + focusScope->setFocus(true); + + //#3 + bottomRect->setFocus(true); + + QCOMPARE(topRectFocusSpy.count(), 2); + QCOMPARE(focusScopeSpy.count(), 2); + + QCOMPARE(topRectFocusSpy.takeFirst().first().toBool(), true); //from #1 + QCOMPARE(topRectFocusSpy.takeFirst().first().toBool(), false); //from #2 + + QCOMPARE(focusScopeSpy.takeFirst().first().toBool(), true); //from #2 + QCOMPARE(focusScopeSpy.takeFirst().first().toBool(), false); //from #3 +} + +void tst_QDeclarativeItem::setFocusThenSetFocusItem0() +{ + //graphicsview init + QGraphicsScene scene; + scene.setFocus(); + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); + + //declarative init + QDeclarativeEngine engine(&scene); + QDeclarativeComponent qmlComponent(&engine); + qmlComponent.setData( + "import QtQuick 1.1;" + "Item {" + "signal focusChangedTo(bool value);" + "signal activeFocusChangedTo(bool value);" + "onFocusChanged: focusChangedTo(focus);" + "onActiveFocusChanged: activeFocusChangedTo(activeFocus);" + "}", QUrl("")); + + QGraphicsItem *createdItem = qobject_cast<QGraphicsItem*>(qmlComponent.create(engine.rootContext())); + QVERIFY(createdItem); + + scene.addItem(createdItem); + + QSignalSpy focusChangedSpy(createdItem->toGraphicsObject(), SIGNAL(focusChangedTo(bool))); + QSignalSpy activeFocusChangedSpy(createdItem->toGraphicsObject(), SIGNAL(activeFocusChangedTo(bool))); + + createdItem->toGraphicsObject()->setFocus(); + QVERIFY(!focusChangedSpy.isEmpty()); + QVERIFY(!activeFocusChangedSpy.isEmpty()); + QCOMPARE(focusChangedSpy.takeFirst().first().toBool(), true); + QCOMPARE(activeFocusChangedSpy.takeFirst().first().toBool(), true); + + scene.setFocusItem(0); + QVERIFY(!focusChangedSpy.isEmpty()); + QVERIFY(!activeFocusChangedSpy.isEmpty()); + QCOMPARE(focusChangedSpy.takeFirst().first().toBool(), false); + QCOMPARE(activeFocusChangedSpy.takeFirst().first().toBool(), false); + QVERIFY(activeFocusChangedSpy.isEmpty()); +} + +void tst_QDeclarativeItem::setFocusFocusItem0ThenHasActiveFocus() +{ + QGraphicsScene scene; + scene.setFocus(); + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); + + QDeclarativeEngine engine(&scene); + QDeclarativeComponent qmlComponent(&engine); + qmlComponent.setData( + "import QtQuick 1.1;" + "TextInput {" + "width: 100; height: 100;" + "Rectangle { anchors.fill: parent; color: \"yellow\"; z: parent.z - 1 }" + "}", QUrl("")); + QDeclarativeItem *createdItem = qobject_cast<QDeclarativeItem*>(qmlComponent.create(engine.rootContext())); + QVERIFY(createdItem != 0); + + scene.addItem(createdItem); + + createdItem->QGraphicsItem::setFocus(); + QCoreApplication::processEvents(); + scene.setFocusItem(0); + QCoreApplication::processEvents(); + + QVERIFY(!createdItem->hasActiveFocus()); +} + QTEST_MAIN(tst_QDeclarativeItem) #include "tst_qdeclarativeitem.moc" |