Expose nextItemInFocusChain in QQuickItem
authorLiang Qi <liang.qi@digia.com>
Fri, 12 Apr 2013 09:52:48 +0000 (11:52 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 23 Apr 2013 10:53:48 +0000 (12:53 +0200)
Convenient for other use cases related with tab focus chain.
Autotest is included.

Change-Id: I1ba6317e20edacc2b672bc5b78e3fcd29ac80bdc
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
src/quick/items/qquickitem.cpp
src/quick/items/qquickitem.h
src/quick/items/qquickitem_p.h
tests/auto/quick/qquickitem2/tst_qquickitem.cpp

index 59ab56d..7e606eb 100644 (file)
@@ -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
index 5dea862..078df2e 100644 (file)
@@ -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
index 4bd9d82..3602b57 100644 (file)
@@ -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;
index f2d25e8..3ec77ce 100644 (file)
@@ -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<QQuickItem>(window->rootObject(), "button11");
+    QVERIFY(button11);
+    QQuickItem *button12 = findItem<QQuickItem>(window->rootObject(), "button12");
+    QVERIFY(button12);
+
+    QQuickItem *sub2 = findItem<QQuickItem>(window->rootObject(), "sub2");
+    QVERIFY(sub2);
+    QQuickItem *button21 = findItem<QQuickItem>(window->rootObject(), "button21");
+    QVERIFY(button21);
+    QQuickItem *button22 = findItem<QQuickItem>(window->rootObject(), "button22");
+    QVERIFY(button22);
+
+    QQuickItem *edit = findItem<QQuickItem>(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);