aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <[email protected]>2022-11-18 14:20:20 +0100
committerVolker Hilsheimer <[email protected]>2022-12-01 06:26:40 +0100
commitd1b9a4cacfb966cf0a37983d8f8044f3aedf5de3 (patch)
tree0124b6f8433f8e3ef9cde5d151ac34af778e4e8b
parent8b100bed5237b1ec864f059d7fb04b94fd874f49 (diff)
QQuickItem: Fix effective visibility for items without parent
Items are visible if they are children of a visible parent, and not explicitly hidden. The effectiveVisible member stores the state and is updated when conditions that impact the item visibility changes. The old code returned true for items outside a visual hierarchy, which broke signal emission when items were removed from a parent, e.g. because the parent got destroyed. With this change, items removed from a visual hierarchy will emit the visibleChanged signal. Note: QQuickItem initializes the effectiveVisible member to true, even if the item was created without parent item. Visual items are required to be added to a visual hierarchy via setParentItem. For this reason, newly created items never emit visibleChanged when they are added to a parent. Adjust the QQuickItem::visible test - it creates an item hierarchy without window. Such items are never visible, so add a window and parent the test item hierarchy to the window's content item. This fixes the expected failures in the tests. It does introduce an incompatibility with QGraphicsView and QGraphicsItem, which continue to return true from QGraphicsItem::isVisible for items that are not in an item hierarchy. [ChangeLog][Qt Quick][QQuickItem] The visible property of Items without a parent now always returns false, and the visibleChanged signal gets emitted when the parent item of a visible item becomes null. Fixes: QTBUG-108213 Change-Id: If4b2947cefd1407853f0f29e6c3fdbd49fc9af65 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Shawn Rutledge <[email protected]>
-rw-r--r--src/quick/items/qquickitem.cpp6
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp2
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp20
3 files changed, 5 insertions, 23 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index a254efb8fc..5f86139566 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6410,10 +6410,8 @@ void QQuickItem::setEnabled(bool e)
bool QQuickItemPrivate::calcEffectiveVisible() const
{
- // XXX todo - Should the effective visible of an element with no parent just be the current
- // effective visible? This would prevent pointless re-processing in the case of an element
- // moving to/from a no-parent situation, but it is different from what graphics view does.
- return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
+ // An item is visible if it is a child of a visible parent, and not explicitly hidden.
+ return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible;
}
bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index e00c4cf42d..23616156d6 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -1094,7 +1094,9 @@ void tst_qquickitem::setParentItem()
void tst_qquickitem::visible()
{
+ QQuickWindow window;
QQuickItem *root = new QQuickItem;
+ root->setParentItem(window.contentItem());
QQuickItem *child1 = new QQuickItem;
child1->setParentItem(root);
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 972755a5f5..f7601cade1 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -4036,7 +4036,7 @@ void tst_QQuickItem::signalsOnDestruction()
// Visual children, but not QObject children.
// Note: QQuickItem's visible property defaults to true after creation, as visual
// items are always expected to be added to a visual hierarchy. So for the sake
- // of this test we first add, and then remove the item from a parent. This explicily
+ // of this test we first add, and then remove the item from a parent. This explicitly
// sets the effective visibility to false.
std::unique_ptr<QQuickItem> parent(new QQuickItem(window.contentItem()));
QVERIFY(parent->isVisible());
@@ -4044,15 +4044,11 @@ void tst_QQuickItem::signalsOnDestruction()
child->setVisible(childVisible);
child->setParentItem(parent.get());
child->setParentItem(nullptr);
- QEXPECT_FAIL("Both visible", "Item without parent should not be visible", Continue);
- QEXPECT_FAIL("Child visible", "Item without parent should not be visible", Continue);
QVERIFY(!child->isVisible());
std::unique_ptr<QQuickItem> grandChild(new QQuickItem);
grandChild->setVisible(grandChildVisible);
grandChild->setParentItem(child.get());
grandChild->setParentItem(nullptr);
- QEXPECT_FAIL("Both visible", "Item without parent should not be visible", Continue);
- QEXPECT_FAIL("Grand child visible", "Item without parent should not be visible", Continue);
QVERIFY(!grandChild->isVisible());
QSignalSpy childrenSpy(parent.get(), &QQuickItem::childrenChanged);
@@ -4070,8 +4066,6 @@ void tst_QQuickItem::signalsOnDestruction()
++expectedChildVisibleCount;
QCOMPARE(visibleChildrenSpy.count(), expectedChildVisibleCount);
QCOMPARE(childParentSpy.count(), 1);
- QEXPECT_FAIL("Both visible", "Child added to visible parent should emit", Continue);
- QEXPECT_FAIL("Child visible", "Child added to visible parent should emit", Continue);
QCOMPARE(childVisibleSpy.count(), expectedChildVisibleCount);
QCOMPARE(childChildrenSpy.count(), 0);
QCOMPARE(childVisibleChildrenSpy.count(), 0);
@@ -4080,16 +4074,12 @@ void tst_QQuickItem::signalsOnDestruction()
QCOMPARE(childrenSpy.count(), 1);
QCOMPARE(visibleChildrenSpy.count(), expectedChildVisibleCount);
QCOMPARE(childParentSpy.count(), 1);
- QEXPECT_FAIL("Both visible", "Child added to visible parent should emit", Continue);
- QEXPECT_FAIL("Child visible", "Child added to visible parent should emit", Continue);
QCOMPARE(childVisibleSpy.count(), expectedChildVisibleCount);
QCOMPARE(childChildrenSpy.count(), 1);
if (grandChildVisible && childVisible)
++expectedGrandChildVisibleCount;
QCOMPARE(childVisibleChildrenSpy.count(), expectedGrandChildVisibleCount);
QCOMPARE(grandChildParentSpy.count(), 1);
- QEXPECT_FAIL("Both visible", "Visible grand child added to visible child should emit", Continue);
- QEXPECT_FAIL("Grand child visible", "Adding visible grand child to hidden child should not emit", Continue);
QCOMPARE(grandChildVisibleSpy.count(), expectedGrandChildVisibleCount);
parent.reset();
@@ -4102,16 +4092,11 @@ void tst_QQuickItem::signalsOnDestruction()
QCOMPARE(childChildrenSpy.count(), 1);
if (childVisible)
++expectedChildVisibleCount;
- QEXPECT_FAIL("Both visible", "Items without (grand) parent should not be visible on screen", Continue);
- QEXPECT_FAIL("Child visible", "Items without (grand) parent should not be visible on screen", Continue);
QCOMPARE(childVisibleSpy.count(), expectedChildVisibleCount);
if (childVisible && grandChildVisible)
++expectedGrandChildVisibleCount;
- QEXPECT_FAIL("Both visible", "Items without (grand) parent should not be visible on screen", Continue);
QCOMPARE(childVisibleChildrenSpy.count(), expectedGrandChildVisibleCount);
QCOMPARE(grandChildParentSpy.count(), 1);
- QEXPECT_FAIL("Both visible", "Items without (grand) parent should not be visible on screen", Continue);
- QEXPECT_FAIL("Grand child visible", "Items without (grand) parent should not be visible on screen", Continue);
QCOMPARE(grandChildVisibleSpy.count(), expectedGrandChildVisibleCount);
}
@@ -4142,9 +4127,7 @@ void tst_QQuickItem::visibleChanged()
QCOMPARE(parentItemSpy.count(), 0);
QCOMPARE(childItemSpy.count(), 0);
QVERIFY(!loaderChild->parentItem());
- QEXPECT_FAIL("", "QTBUG-108213", Continue);
QCOMPARE(loaderChildSpy.count(), 1);
- QEXPECT_FAIL("", "QTBUG-108213", Continue);
QCOMPARE(loaderChild->isVisible(), false);
delete parentItem.data();
@@ -4153,7 +4136,6 @@ void tst_QQuickItem::visibleChanged()
QVERIFY(!childItem->parentItem());
QCOMPARE(parentItemSpy.count(), 0);
- QEXPECT_FAIL("", "QTBUG-108213", Continue);
QCOMPARE(childItemSpy.count(), 1);
}