diff options
author | Chen Bin <chenbin@uniontech.com> | 2022-06-24 10:38:51 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-06-27 05:54:20 +0000 |
commit | c54bf3d73c7102c7eee1b04449eab05e637bb8eb (patch) | |
tree | e3fa012667589785e2596e4e5f9c37aa38469a98 | |
parent | 3939b681357fa97d9c2cb3fbd9937d4693dd6d98 (diff) |
Repeater: uncull items that come from ObjectModel
After 6173fc0e4be93604286b9a424f1aa3ff5896082a, Menu will
unconditionally cull items as they are inserted. This behavior relies
on the fact that ListView will uncull the items as necessary. However,
when implementing Menu with a Repeater as the contentItem (which is
unusual but not unreasonable), the items will never be unculled and
hence will be invisible.
We can't fix this in Menu by checking its contentItem, because when
items are inserted, their parent item is the root contentItem, not the
Repeater, and there's no nice, efficient way to check if the item
belongs to a Repeater.
This patch fixes the issue in Repeater by unculling the item if it
came from an ObjectModel.
Done-with: Mitch Curtis <mitch.curtis@qt.io>
Fixes: QTBUG-104544
Change-Id: Ib37d2d49d3608156a3f1e3652b63ccdd5dfd0f41
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit 19637c2241724cac55315afbb70b5f4333a2065b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
3 files changed, 90 insertions, 0 deletions
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 2ae804f146..3ce18a7a6e 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -403,6 +403,11 @@ void QQuickRepeater::initItem(int index, QObject *object) } d->deletables[index] = item; item->setParentItem(parentItem()); + + // If the item comes from an ObjectModel, it might be used as Menu's contentItem. + // Menu unconditionally culls items that are inserted, so account for that here. + if (d->dataSourceIsObject) + QQuickItemPrivate::get(item)->setCulled(false); if (index > 0 && d->deletables.at(index-1)) { item->stackAfter(d->deletables.at(index-1)); } else { diff --git a/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml b/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml new file mode 100644 index 0000000000..bfa8f66be5 --- /dev/null +++ b/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml @@ -0,0 +1,65 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +ApplicationWindow { + width: 200 + height: 200 + property alias menu: menu + + Menu { + id: menu + visible: true + + contentItem: FocusScope { + implicitHeight: flickable.height + + Button { + anchors { + top: parent.top + topMargin: 5 + horizontalCenter: parent.horizontalCenter + } + z: 1 + text: "Button Up" + } + + Flickable { + id: flickable + width: parent.width + height: Math.min(contentHeight, 300) + contentHeight: repeaterLayout.implicitHeight + clip: true + + ScrollIndicator.vertical: ScrollIndicator {} + + ColumnLayout { + id: repeaterLayout + width: parent.width + + Repeater { + model: menu.contentModel + } + } + } + + Button { + anchors { + bottom: parent.bottom + bottomMargin: 5 + horizontalCenter: parent.horizontalCenter + } + z: 1 + text: "Button Down" + } + } + + Repeater { + model: 20 + MenuItem { + objectName: "Item: " + modelData + text: objectName + } + } + } +} diff --git a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp index d7ec942c14..b2fc3b6258 100644 --- a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp @@ -79,6 +79,7 @@ private slots: void menuItemWidthAfterRetranslate(); void giveMenuItemFocusOnButtonPress(); void customMenuCullItems(); + void customMenuUseRepeaterAsTheContentItem(); }; tst_QQuickMenu::tst_QQuickMenu() @@ -1999,6 +2000,25 @@ void tst_QQuickMenu::customMenuCullItems() QTRY_VERIFY(QQuickItemPrivate::get(menuItemLast)->culled); } +void tst_QQuickMenu::customMenuUseRepeaterAsTheContentItem() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("customMenuUseRepeaterAsTheContentItem.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); + QVERIFY(menu); + menu->open(); + QTRY_VERIFY(menu->isVisible()); + + QQuickItem *menuItemFirst = menu->itemAt(0); + QQuickItem *menuItemLast = menu->itemAt(menu->count() - 1); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItemFirst)->culled); + QTRY_VERIFY(!QQuickItemPrivate::get(menuItemLast)->culled); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu) #include "tst_qquickmenu.moc" |