diff options
-rw-r--r-- | src/quickcontrols2/qquicktumblerview.cpp | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 4 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontainer.cpp | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenu.cpp | 42 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenu_p_p.h | 3 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_combobox.qml | 25 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_container.qml | 27 | ||||
-rw-r--r-- | tests/auto/menu/tst_menu.cpp | 113 |
8 files changed, 192 insertions, 30 deletions
diff --git a/src/quickcontrols2/qquicktumblerview.cpp b/src/quickcontrols2/qquicktumblerview.cpp index 59f443d5..817ec370 100644 --- a/src/quickcontrols2/qquicktumblerview.cpp +++ b/src/quickcontrols2/qquicktumblerview.cpp @@ -170,7 +170,7 @@ void QQuickTumblerView::createView() } } -// Called whever the size or visibleItemCount changes. +// Called whenever the size or visibleItemCount changes. void QQuickTumblerView::updateView() { QQuickItem *theView = view(); diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index a6f9f6ca..dceda7d7 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -204,6 +204,10 @@ QString QQuickComboBoxDelegateModel::stringValue(int index, const QString &role) if (data.count() == 1 && role == QLatin1String("modelData")) return data.first().toString(); return data.value(role).toString(); + } else if (object.userType() == QMetaType::QObjectStar) { + const QObject *data = object.value<QObject *>(); + if (data && role != QLatin1String("modelData")) + return data->property(role.toUtf8()).toString(); } } return QQmlDelegateModel::stringValue(index, role); diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp index 9b8298c2..eaf18714 100644 --- a/src/quicktemplates2/qquickcontainer.cpp +++ b/src/quicktemplates2/qquickcontainer.cpp @@ -350,10 +350,14 @@ void QQuickContainerPrivate::itemSiblingOrderChanged(QQuickItem *) // reorder the restacked items (eg. by a Repeater) Q_Q(QQuickContainer); QList<QQuickItem *> siblings = effectiveContentItem(contentItem)->childItems(); + + int to = 0; for (int i = 0; i < siblings.count(); ++i) { QQuickItem* sibling = siblings.at(i); + if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner()) + continue; int index = contentModel->indexOf(sibling, nullptr); - q->moveItem(index, i); + q->moveItem(index, to++); } } diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index 5a2ad066..8639e504 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -330,10 +330,14 @@ void QQuickMenuPrivate::itemSiblingOrderChanged(QQuickItem *) // reorder the restacked items (eg. by a Repeater) Q_Q(QQuickMenu); QList<QQuickItem *> siblings = contentItem->childItems(); + + int to = 0; for (int i = 0; i < siblings.count(); ++i) { QQuickItem* sibling = siblings.at(i); + if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner()) + continue; int index = contentModel->indexOf(sibling, nullptr); - q->moveItem(index, i); + q->moveItem(index, to++); } } @@ -513,6 +517,31 @@ void QQuickMenuPrivate::setCurrentIndex(int index) } } +void QQuickMenuPrivate::activateNextItem() +{ + int index = currentIndex(); + int count = contentModel->count(); + while (++index < count) { + QQuickItem *item = itemAt(index); + if (!item || !item->activeFocusOnTab()) + continue; + item->forceActiveFocus(Qt::TabFocusReason); + break; + } +} + +void QQuickMenuPrivate::activatePreviousItem() +{ + int index = currentIndex(); + while (--index >= 0) { + QQuickItem *item = itemAt(index); + if (!item || !item->activeFocusOnTab()) + continue; + item->forceActiveFocus(Qt::BacktabFocusReason); + break; + } +} + void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) { QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object); @@ -1158,13 +1187,11 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event) // shown at once. switch (event->key()) { case Qt::Key_Up: - if (d->contentItem->metaObject()->indexOfMethod("decrementCurrentIndex()") != -1) - QMetaObject::invokeMethod(d->contentItem, "decrementCurrentIndex"); + d->activatePreviousItem(); break; case Qt::Key_Down: - if (d->contentItem->metaObject()->indexOfMethod("incrementCurrentIndex()") != -1) - QMetaObject::invokeMethod(d->contentItem, "incrementCurrentIndex"); + d->activateNextItem(); break; case Qt::Key_Left: @@ -1180,11 +1207,6 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event) default: break; } - - int index = d->currentIndex(); - QQuickItem *item = itemAt(index); - if (item) - item->forceActiveFocus(); } void QQuickMenu::timerEvent(QTimerEvent *event) diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index 5887d4e5..a81c87c2 100644 --- a/src/quicktemplates2/qquickmenu_p_p.h +++ b/src/quicktemplates2/qquickmenu_p_p.h @@ -108,6 +108,9 @@ public: int currentIndex() const; void setCurrentIndex(int index); + void activateNextItem(); + void activatePreviousItem(); + static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj); static int contentData_count(QQmlListProperty<QObject> *prop); static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index); diff --git a/tests/auto/controls/data/tst_combobox.qml b/tests/auto/controls/data/tst_combobox.qml index 4f969106..136c0830 100644 --- a/tests/auto/controls/data/tst_combobox.qml +++ b/tests/auto/controls/data/tst_combobox.qml @@ -156,6 +156,31 @@ TestCase { compare(control.currentText, "") } + function test_qobjects() { + var control = createTemporaryObject(emptyBox, testCase, {textRole: "text"}) + verify(control) + + var obj1 = Qt.createQmlObject("import QtQml 2.0; QtObject { property string text: 'one' }", control) + var obj2 = Qt.createQmlObject("import QtQml 2.0; QtObject { property string text: 'two' }", control) + var obj3 = Qt.createQmlObject("import QtQml 2.0; QtObject { property string text: 'three' }", control) + + control.model = [obj1, obj2, obj3] + + compare(control.count, 3) + compare(control.currentIndex, 0) + compare(control.currentText, "one") + + control.currentIndex = 2 + compare(control.currentIndex, 2) + compare(control.currentText, "three") + + control.model = null + compare(control.model, null) + compare(control.count, 0) + compare(control.currentIndex, -1) + compare(control.currentText, "") + } + function test_number() { var control = createTemporaryObject(comboBox, testCase) verify(control) diff --git a/tests/auto/controls/data/tst_container.qml b/tests/auto/controls/data/tst_container.qml index 44d8e67a..94f22ad2 100644 --- a/tests/auto/controls/data/tst_container.qml +++ b/tests/auto/controls/data/tst_container.qml @@ -127,6 +127,33 @@ TestCase { compare(control2.currentIndex, 1) } + Component { + id: repeaterContainer + Container { + id: container + Item { objectName: "0" } + Item { objectName: "1" } + Item { objectName: "2" } + Item { objectName: "3" } + contentItem: Row { + Repeater { + model: container.contentModel + } + } + } + } + + // don't crash (QTBUG-61310) + function test_repeater() { + var control = createTemporaryObject(repeaterContainer) + verify(control) + + compare(control.itemAt(0).objectName, "0") + compare(control.itemAt(1).objectName, "1") + compare(control.itemAt(2).objectName, "2") + compare(control.itemAt(3).objectName, "3") + } + function test_removeTakeItem() { var control = createTemporaryObject(container, testCase) verify(control) diff --git a/tests/auto/menu/tst_menu.cpp b/tests/auto/menu/tst_menu.cpp index 5cf25168..79a459b8 100644 --- a/tests/auto/menu/tst_menu.cpp +++ b/tests/auto/menu/tst_menu.cpp @@ -194,7 +194,8 @@ void tst_menu::contextMenuKeyboard() QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - QQuickItem *firstItem = menu->itemAt(0); + QQuickMenuItem *firstItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(0)); + QVERIFY(firstItem); QSignalSpy visibleSpy(menu, SIGNAL(visibleChanged())); menu->setFocus(true); @@ -208,15 +209,21 @@ void tst_menu::contextMenuKeyboard() QTest::keyClick(window, Qt::Key_Tab); QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->property("highlighted").toBool()); + QVERIFY(firstItem->hasVisualFocus()); + QVERIFY(firstItem->isHighlighted()); + QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); - QQuickItem *secondItem = menu->itemAt(1); + QQuickMenuItem *secondItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(1)); + QVERIFY(secondItem); QTest::keyClick(window, Qt::Key_Tab); QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); QVERIFY(secondItem->hasActiveFocus()); - QVERIFY(secondItem->property("highlighted").toBool()); + QVERIFY(secondItem->hasVisualFocus()); + QVERIFY(secondItem->isHighlighted()); + QCOMPARE(secondItem->focusReason(), Qt::TabFocusReason); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(1)); QSignalSpy secondTriggeredSpy(secondItem, SIGNAL(triggered())); @@ -226,9 +233,11 @@ void tst_menu::contextMenuKeyboard() QVERIFY(!menu->isVisible()); QVERIFY(!window->overlay()->childItems().contains(menu->contentItem())); QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->property("highlighted").toBool()); + QVERIFY(!secondItem->hasVisualFocus()); + QVERIFY(!secondItem->isHighlighted()); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); menu->open(); @@ -236,36 +245,75 @@ void tst_menu::contextMenuKeyboard() QVERIFY(menu->isVisible()); QVERIFY(window->overlay()->childItems().contains(menu->contentItem()->parentItem())); QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->property("highlighted").toBool()); + QVERIFY(!secondItem->hasVisualFocus()); + QVERIFY(!secondItem->isHighlighted()); QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); QTest::keyClick(window, Qt::Key_Down); QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->property("highlighted").toBool()); + QVERIFY(firstItem->hasVisualFocus()); + QVERIFY(firstItem->isHighlighted()); + QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); QTest::keyClick(window, Qt::Key_Down); QVERIFY(secondItem->hasActiveFocus()); - QVERIFY(secondItem->property("highlighted").toBool()); + QVERIFY(secondItem->hasVisualFocus()); + QVERIFY(secondItem->isHighlighted()); + QCOMPARE(secondItem->focusReason(), Qt::TabFocusReason); QTest::keyClick(window, Qt::Key_Down); - QQuickItem *thirdItem = menu->itemAt(2); + QQuickMenuItem *thirdItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(2)); + QVERIFY(thirdItem); QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->property("highlighted").toBool()); + QVERIFY(!secondItem->hasVisualFocus()); + QVERIFY(!secondItem->isHighlighted()); QVERIFY(thirdItem->hasActiveFocus()); - QVERIFY(thirdItem->property("highlighted").toBool()); + QVERIFY(thirdItem->hasVisualFocus()); + QVERIFY(thirdItem->isHighlighted()); + QCOMPARE(thirdItem->focusReason(), Qt::TabFocusReason); // Key navigation shouldn't wrap by default. QTest::keyClick(window, Qt::Key_Down); QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->property("highlighted").toBool()); + QVERIFY(!secondItem->hasVisualFocus()); + QVERIFY(!secondItem->isHighlighted()); QVERIFY(thirdItem->hasActiveFocus()); - QVERIFY(thirdItem->property("highlighted").toBool()); + QVERIFY(thirdItem->hasVisualFocus()); + QVERIFY(thirdItem->isHighlighted()); + QCOMPARE(thirdItem->focusReason(), Qt::TabFocusReason); + + QTest::keyClick(window, Qt::Key_Up); + QVERIFY(!firstItem->hasActiveFocus()); + QVERIFY(!firstItem->hasVisualFocus()); + QVERIFY(!firstItem->isHighlighted()); + QVERIFY(secondItem->hasActiveFocus()); + QVERIFY(secondItem->hasVisualFocus()); + QVERIFY(secondItem->isHighlighted()); + QCOMPARE(secondItem->focusReason(), Qt::BacktabFocusReason); + QVERIFY(!thirdItem->hasActiveFocus()); + QVERIFY(!thirdItem->hasVisualFocus()); + QVERIFY(!thirdItem->isHighlighted()); + + QTest::keyClick(window, Qt::Key_Backtab); + QVERIFY(firstItem->hasActiveFocus()); + QVERIFY(firstItem->hasVisualFocus()); + QVERIFY(firstItem->isHighlighted()); + QCOMPARE(firstItem->focusReason(), Qt::BacktabFocusReason); + QVERIFY(!secondItem->hasActiveFocus()); + QVERIFY(!secondItem->hasVisualFocus()); + QVERIFY(!secondItem->isHighlighted()); + QVERIFY(!thirdItem->hasActiveFocus()); + QVERIFY(!thirdItem->hasVisualFocus()); + QVERIFY(!thirdItem->isHighlighted()); QTest::keyClick(window, Qt::Key_Escape); QCOMPARE(visibleSpy.count(), 4); @@ -362,6 +410,35 @@ void tst_menu::menuSeparator() QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, saveMenuItem->mapToScene(QPointF(saveMenuItem->width() / 2, saveMenuItem->height() / 2)).toPoint()); QTRY_VERIFY(!menu->isVisible()); + + menu->open(); + QVERIFY(menu->isVisible()); + + // Key navigation skips separators + QTest::keyClick(window, Qt::Key_Down); + QVERIFY(newMenuItem->hasActiveFocus()); + QVERIFY(newMenuItem->hasVisualFocus()); + QCOMPARE(newMenuItem->focusReason(), Qt::TabFocusReason); + + QTest::keyClick(window, Qt::Key_Down); + QVERIFY(saveMenuItem->hasActiveFocus()); + QVERIFY(saveMenuItem->hasVisualFocus()); + QCOMPARE(saveMenuItem->focusReason(), Qt::TabFocusReason); + + QTest::keyClick(window, Qt::Key_Down); + QVERIFY(saveMenuItem->hasActiveFocus()); + QVERIFY(saveMenuItem->hasVisualFocus()); + QCOMPARE(saveMenuItem->focusReason(), Qt::TabFocusReason); + + QTest::keyClick(window, Qt::Key_Up); + QVERIFY(newMenuItem->hasActiveFocus()); + QVERIFY(newMenuItem->hasVisualFocus()); + QCOMPARE(newMenuItem->focusReason(), Qt::BacktabFocusReason); + + QTest::keyClick(window, Qt::Key_Up); + QVERIFY(newMenuItem->hasActiveFocus()); + QVERIFY(newMenuItem->hasVisualFocus()); + QCOMPARE(newMenuItem->focusReason(), Qt::BacktabFocusReason); } void tst_menu::repeater() |