aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickitem.cpp
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-07-13 11:22:11 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-07-13 13:00:13 +0000
commit35d500526990fafe5b71d97b051a770a2a81e82a (patch)
tree4af57439b5b58fb2cf0e0a20f18429ff2fcd2bd7 /src/quick/items/qquickitem.cpp
parent15621772e288c33d697cb7345ee04b8c33436d1f (diff)
Fix itemGeometryChanged() listeners
We must iterate a (cheap) copy of changeListeners, because the container might be indirectly modified during the loop. For example, listeners may remove themselves from the list. In such scenario, the copy gets detached and the loop remains safe. I've added notes in comments, and extended the tests to prevent the issue re-surfacing again. Change-Id: Ib48d6e0765d45370d2fffa119a4c351e0119e40a Task-number: QTBUG-54732 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quick/items/qquickitem.cpp')
-rw-r--r--src/quick/items/qquickitem.cpp25
1 files changed, 13 insertions, 12 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 79ddd449f5..07a415eecd 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2329,7 +2329,7 @@ QQuickItem::~QQuickItem()
while (!d->childItems.isEmpty())
d->childItems.constFirst()->setParentItem(0);
- const auto listeners = d->changeListeners;
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
if (anchor)
@@ -3572,7 +3572,7 @@ QQuickAnchors *QQuickItemPrivate::anchors() const
void QQuickItemPrivate::siblingOrderChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::SiblingOrder) {
change.listener->itemSiblingOrderChanged(q);
@@ -3686,7 +3686,8 @@ void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
change.setWidthChange(diff.width() != 0);
change.setHeightChange(diff.height() != 0);
- for (const QQuickItemPrivate::ChangeListener &listener : qAsConst(d->changeListeners)) {
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
+ for (const QQuickItemPrivate::ChangeListener &listener : listeners) {
if (listener.types & QQuickItemPrivate::Geometry) {
if (change.matches(listener.gTypes))
listener.listener->itemGeometryChanged(this, change, diff);
@@ -4245,7 +4246,7 @@ void QQuickItem::setBaselineOffset(qreal offset)
d->baselineOffset = offset;
- const auto listeners = d->changeListeners;
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Geometry) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
@@ -5920,7 +5921,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
switch (change) {
case QQuickItem::ItemChildAddedChange: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildAdded(q, data.item);
@@ -5930,7 +5931,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemChildRemovedChange: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildRemoved(q, data.item);
@@ -5943,7 +5944,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
break;
case QQuickItem::ItemVisibleHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Visibility) {
change.listener->itemVisibilityChanged(q);
@@ -5953,7 +5954,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemParentHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Parent) {
change.listener->itemParentChanged(q, data.item);
@@ -5963,7 +5964,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemOpacityHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Opacity) {
change.listener->itemOpacityChanged(q);
@@ -5976,7 +5977,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
break;
case QQuickItem::ItemRotationHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Rotation) {
change.listener->itemRotationChanged(q);
@@ -6338,7 +6339,7 @@ void QQuickItem::resetWidth()
void QQuickItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitWidth) {
change.listener->itemImplicitWidthChanged(q);
@@ -6502,7 +6503,7 @@ void QQuickItem::resetHeight()
void QQuickItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitHeight) {
change.listener->itemImplicitHeightChanged(q);