QmlDesigner: Update repeater parent when repeater properties change

Any time repeater properties change, the repeater parent should be
dirtied to ensure it rerenders. Often the rerender is triggered
incidentally due to other triggers, but e.g. in case model value is
changed to zero, or if model property is removed, no other trigger
causes rerender.

Also moved the repeater parent checks into QuickItemNodeInstance
to avoid polluting Qt5NodeInstanceServer with such stuff.

Fixes: QDS-5233
Change-Id: Idd89e23c5ad022d26f443d665dac81dc2cbb0b28
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2021-10-08 13:59:02 +03:00
parent 3395cdfd26
commit 9b6f60992c
4 changed files with 38 additions and 44 deletions

View File

@@ -37,7 +37,6 @@
#include <addimportcontainer.h>
#include <createscenecommand.h>
#include <reparentinstancescommand.h>
#include <removeinstancescommand.h>
#include <clearscenecommand.h>
#include <QDebug>
@@ -194,32 +193,6 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
return QList<QQuickItem*>();
}
void Qt5NodeInstanceServer::markRepeaterParentDirty(qint32 id) const
{
if (!hasInstanceForId(id))
return;
ServerNodeInstance instance = instanceForId(id);
if (!instance.isValid())
return;
ServerNodeInstance parentInstance = instance.parent();
if (!parentInstance.isValid())
return;
// If a Repeater instance was moved/removed, the old parent must be marked dirty to rerender it
const QByteArray type("QQuickRepeater");
if (ServerNodeInstance::isSubclassOf(instance.internalObject(), type))
DesignerSupport::addDirty(parentInstance.rootQuickItem(), QQuickDesignerSupport::Content);
// Repeater's parent must also be dirtied when a child of a repeater was moved/removed.
if (ServerNodeInstance::isSubclassOf(parentInstance.internalObject(), type)) {
ServerNodeInstance parentsParent = parentInstance.parent();
if (parentsParent.isValid())
DesignerSupport::addDirty(parentsParent.rootQuickItem(), QQuickDesignerSupport::Content);
}
}
bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -550,23 +523,8 @@ void Qt5NodeInstanceServer::clearScene(const ClearSceneCommand &command)
void Qt5NodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
{
const QVector<ReparentContainer> &containerVector = command.reparentInstances();
for (const ReparentContainer &container : containerVector)
markRepeaterParentDirty(container.instanceId());
NodeInstanceServer::reparentInstances(command.reparentInstances());
startRenderTimer();
}
void Qt5NodeInstanceServer::removeInstances(const RemoveInstancesCommand &command)
{
const QVector<qint32> &idVector = command.instanceIds();
for (const qint32 id : idVector)
markRepeaterParentDirty(id);
NodeInstanceServer::removeInstances(command);
startRenderTimer();
}
} // QmlDesigner

View File

@@ -67,7 +67,6 @@ public:
void createScene(const CreateSceneCommand &command) override;
void clearScene(const ClearSceneCommand &command) override;
void reparentInstances(const ReparentInstancesCommand &command) override;
void removeInstances(const RemoveInstancesCommand &command) override;
QImage grabWindow() override;
QImage grabItem(QQuickItem *item) override;
@@ -80,7 +79,6 @@ protected:
void resetAllItems();
void setupScene(const CreateSceneCommand &command) override;
QList<QQuickItem*> allItems() const;
void markRepeaterParentDirty(qint32 id) const;
struct RenderViewData {
QPointer<QQuickWindow> window = nullptr;

View File

@@ -767,6 +767,8 @@ void QuickItemNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParen
setMovable(true);
}
markRepeaterParentDirty();
ObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
if (!newParentInstance)
@@ -831,6 +833,8 @@ void QuickItemNodeInstance::setPropertyVariant(const PropertyName &name, const Q
if (name == "layer.enabled" || name == "layer.effect")
setAllNodesDirtyRecursive(quickItem());
markRepeaterParentDirty();
ObjectNodeInstance::setPropertyVariant(name, value);
refresh();
@@ -850,6 +854,8 @@ void QuickItemNodeInstance::setPropertyBinding(const PropertyName &name, const Q
if (name.startsWith("anchors.") && isRootNodeInstance())
return;
markRepeaterParentDirty();
ObjectNodeInstance::setPropertyBinding(name, expression);
refresh();
@@ -927,6 +933,8 @@ void QuickItemNodeInstance::resetProperty(const PropertyName &name)
resetVertical();
}
markRepeaterParentDirty();
ObjectNodeInstance::resetProperty(name);
if (isInLayoutable())
@@ -1003,6 +1011,35 @@ QQuickItem *QuickItemNodeInstance::quickItem() const
return static_cast<QQuickItem*>(object());
}
void QuickItemNodeInstance::markRepeaterParentDirty() const
{
const qint32 id = instanceId();
if (id <= 0 && !isValid())
return;
QQuickItem *item = quickItem();
if (!item)
return;
QQuickItem *parentItem = item->parentItem();
if (!parentItem)
return;
// If a Repeater instance was changed in any way, the parent must be marked dirty to rerender it
const QByteArray type("QQuickRepeater");
if (ServerNodeInstance::isSubclassOf(item, type))
DesignerSupport::addDirty(parentItem, QQuickDesignerSupport::Content);
// Repeater's parent must also be dirtied when a child of a repeater was changed
if (ServerNodeInstance::isSubclassOf(parentItem, type)) {
QQuickItem *parentsParent = parentItem->parentItem();
if (parentsParent)
DesignerSupport::addDirty(parentsParent, QQuickDesignerSupport::Content);
}
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -130,6 +130,7 @@ protected:
double x() const;
double y() const;
bool checkIfRefFromEffect(qint32 id);
void markRepeaterParentDirty() const;
private: //variables
QPointer<QQuickItem> m_contentItem;