aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Bin <chenbin@uniontech.com>2022-06-24 10:38:51 +0800
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-06-27 05:54:20 +0000
commitc54bf3d73c7102c7eee1b04449eab05e637bb8eb (patch)
treee3fa012667589785e2596e4e5f9c37aa38469a98
parent3939b681357fa97d9c2cb3fbd9937d4693dd6d98 (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>
-rw-r--r--src/quick/items/qquickrepeater.cpp5
-rw-r--r--tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml65
-rw-r--r--tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp20
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"