From 7167ebd3012147b41a447a6b0bbecc64b6017bd4 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 12 Apr 2013 11:52:48 +0200 Subject: [PATCH] Expose nextItemInFocusChain in QQuickItem Convenient for other use cases related with tab focus chain. Autotest is included. Change-Id: I1ba6317e20edacc2b672bc5b78e3fcd29ac80bdc Reviewed-by: Jerome Pasion Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickitem.cpp | 41 ++++++++++++-- src/quick/items/qquickitem.h | 1 + src/quick/items/qquickitem_p.h | 1 + tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 75 +++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 59ab56d..7e606eb 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2044,6 +2044,18 @@ QQuickItem::~QQuickItem() */ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward) { + QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward); + + if (next == item) + return false; + + next->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason); + + return true; +} + +QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward) +{ Q_ASSERT(item); Q_ASSERT(item->activeFocusOnTab()); @@ -2111,12 +2123,7 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward) from = last; } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()); - if (current == item) - return false; - - current->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason); - - return true; + return current; } /*! @@ -3928,6 +3935,28 @@ void QQuickItem::forceActiveFocus(Qt::FocusReason reason) } /*! + \qmlmethod QtQuick2::Item::nextItemInFocusChain(bool forward) + + \since QtQuick 2.1 + + Returns the item in the focus chain which is next to this item. + If \a forward is \c true, or not supplied, it is the next item in + the forwards direction. If \a forward is \c false, it is the next + item in the backwards direction. +*/ +/*! + Returns the item in the focus chain which is next to this item. + If \a forward is \c true, or not supplied, it is the next item in + the forwards direction. If \a forward is \c false, it is the next + item in the backwards direction. +*/ + +QQuickItem *QQuickItem::nextItemInFocusChain(bool forward) +{ + return QQuickItemPrivate::nextPrevItemInTabFocusChain(this, forward); +} + +/*! \qmlmethod QtQuick2::Item::childAt(real x, real y) Returns the first visible child item found at point (\a x, \a y) within diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 5dea862..078df2e 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -324,6 +324,7 @@ public: Q_INVOKABLE void mapToItem(QQmlV8Function*) const; Q_INVOKABLE void forceActiveFocus(); Q_INVOKABLE void forceActiveFocus(Qt::FocusReason reason); + Q_INVOKABLE QQuickItem *nextItemInFocusChain(bool forward = true); Q_INVOKABLE QQuickItem *childAt(qreal x, qreal y) const; #ifndef QT_NO_IM diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 4bd9d82..3602b57 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -485,6 +485,7 @@ public: void itemToParentTransform(QTransform &) const; static bool focusNextPrev(QQuickItem *item, bool forward); + static QQuickItem *nextPrevItemInTabFocusChain(QQuickItem *item, bool forward); qreal x; qreal y; diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index f2d25e8..3ec77ce 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -70,6 +70,8 @@ private slots: void activeFocusOnTab4(); void activeFocusOnTab5(); + void nextItemInFocusChain(); + void keys(); void keysProcessingOrder(); void keysim(); @@ -664,6 +666,79 @@ void tst_QQuickItem::activeFocusOnTab5() delete window; } +void tst_QQuickItem::nextItemInFocusChain() +{ + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(800,600)); + + window->setSource(testFileUrl("activeFocusOnTab.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *button11 = findItem(window->rootObject(), "button11"); + QVERIFY(button11); + QQuickItem *button12 = findItem(window->rootObject(), "button12"); + QVERIFY(button12); + + QQuickItem *sub2 = findItem(window->rootObject(), "sub2"); + QVERIFY(sub2); + QQuickItem *button21 = findItem(window->rootObject(), "button21"); + QVERIFY(button21); + QQuickItem *button22 = findItem(window->rootObject(), "button22"); + QVERIFY(button22); + + QQuickItem *edit = findItem(window->rootObject(), "edit"); + QVERIFY(edit); + + QQuickItem *next, *prev; + + next = button11->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, button12); + prev = button11->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, edit); + + next = button12->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, sub2); + prev = button12->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button11); + + next = sub2->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, button21); + prev = sub2->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button12); + + next = button21->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, button22); + prev = button21->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, sub2); + + next = button22->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, edit); + prev = button22->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button21); + + next = edit->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, button11); + prev = edit->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button22); + + delete window; +} + void tst_QQuickItem::keys() { QQuickView *window = new QQuickView(0); -- 2.7.4