From 2a44f8caafbe8d7ed85c136616f9e82ce0973893 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 16 Nov 2022 14:15:53 +0100 Subject: [PATCH] QmlDesigner: Fix shaking items when scrubbing the timeline The reason for this is that when scrubbing the timeline, the bounding rectangle can change a lot (See bugreport). If this is the case the pixmap and the bounding rectangle get temporarily out of sync, which leads to the shaking. In this patch we add the bounding rectangle to the pixmap command. The bounding rectangle coming with the pixmap has higher precedence. This means if there is a pixmap, then the pixmap is always in sync with the pixmap. If there is no pixmap we use the "original" bounding rectangle. Task-number: QDS-7828 Change-Id: I40c0b7ed97863b9dca726547927ae1a37f9c415d Reviewed-by: Tim Jenssen --- .../container/imagecontainer.cpp | 12 ++++++++++ .../container/imagecontainer.h | 16 +++++++++----- .../interfaces/commondefines.h | 5 ++--- .../designercore/include/nodeinstance.h | 1 + .../designercore/instances/nodeinstance.cpp | 22 ++++++++++++++++--- .../instances/nodeinstanceview.cpp | 18 +++++++++++++++ .../instances/nodeinstanceserver.cpp | 4 +++- 7 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp b/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp index d71ba4769ee..007010feb46 100644 --- a/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp +++ b/src/libs/qmlpuppetcommunication/container/imagecontainer.cpp @@ -51,6 +51,11 @@ qint32 ImageContainer::keyNumber() const return m_keyNumber; } +QRectF ImageContainer::rect() const +{ + return m_rect; +} + void ImageContainer::setImage(const QImage &image) { QTC_ASSERT(m_image.isNull(), /**/); @@ -58,6 +63,11 @@ void ImageContainer::setImage(const QImage &image) m_image = image; } +void ImageContainer::setRect(const QRectF &rectangle) +{ + m_rect = rectangle; +} + void ImageContainer::removeSharedMemorys(const QVector &keyNumberVector) { for (qint32 keyNumber : keyNumberVector) { @@ -140,6 +150,7 @@ QDataStream &operator<<(QDataStream &out, const ImageContainer &container) out << container.instanceId(); out << container.keyNumber(); + out << container.rect(); const QImage image = container.image(); @@ -223,6 +234,7 @@ QDataStream &operator>>(QDataStream &in, ImageContainer &container) in >> container.m_instanceId; in >> container.m_keyNumber; + in >> container.m_rect; in >> sharedMemoryIsUsed; if (sharedMemoryIsUsed) { diff --git a/src/libs/qmlpuppetcommunication/container/imagecontainer.h b/src/libs/qmlpuppetcommunication/container/imagecontainer.h index c6c101ca8c4..67a95e2f8f7 100644 --- a/src/libs/qmlpuppetcommunication/container/imagecontainer.h +++ b/src/libs/qmlpuppetcommunication/container/imagecontainer.h @@ -3,16 +3,17 @@ #pragma once -#include #include +#include +#include namespace QmlDesigner { class ImageContainer { friend QDataStream &operator>>(QDataStream &in, ImageContainer &container); - friend bool operator ==(const ImageContainer &first, const ImageContainer &second); - friend bool operator <(const ImageContainer &first, const ImageContainer &second); + friend bool operator==(const ImageContainer &first, const ImageContainer &second); + friend bool operator<(const ImageContainer &first, const ImageContainer &second); public: ImageContainer(); @@ -21,8 +22,10 @@ public: qint32 instanceId() const; QImage image() const; qint32 keyNumber() const; + QRectF rect() const; void setImage(const QImage &image); + void setRect(const QRectF &rectangle); static void removeSharedMemorys(const QVector &keyNumberVector); @@ -30,14 +33,15 @@ private: QImage m_image; qint32 m_instanceId; qint32 m_keyNumber; + QRectF m_rect; }; QDataStream &operator<<(QDataStream &out, const ImageContainer &container); QDataStream &operator>>(QDataStream &in, ImageContainer &container); -bool operator ==(const ImageContainer &first, const ImageContainer &second); -bool operator <(const ImageContainer &first, const ImageContainer &second); -QDebug operator <<(QDebug debug, const ImageContainer &container); +bool operator==(const ImageContainer &first, const ImageContainer &second); +bool operator<(const ImageContainer &first, const ImageContainer &second); +QDebug operator<<(QDebug debug, const ImageContainer &container); } // namespace QmlDesigner diff --git a/src/libs/qmlpuppetcommunication/interfaces/commondefines.h b/src/libs/qmlpuppetcommunication/interfaces/commondefines.h index 7909c097b05..ef651748581 100644 --- a/src/libs/qmlpuppetcommunication/interfaces/commondefines.h +++ b/src/libs/qmlpuppetcommunication/interfaces/commondefines.h @@ -8,13 +8,13 @@ namespace QmlDesigner { -enum InformationName -{ +enum InformationName { NoName, NoInformationChange = NoName, AllStates, Size, BoundingRect, + BoundingRectPixmap, Transform, HasAnchor, Anchor, @@ -37,5 +37,4 @@ enum InformationName ResizeView, HideView }; - } diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstance.h b/src/plugins/qmldesigner/designercore/include/nodeinstance.h index dc8c02582eb..67685a30999 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstance.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstance.h @@ -80,6 +80,7 @@ protected: InformationName setInformationSize(const QSizeF &size); InformationName setInformationBoundingRect(const QRectF &rectangle); + InformationName setInformationBoundingRectPixmap(const QRectF &rectangle); InformationName setInformationContentItemBoundingRect(const QRectF &rectangle); InformationName setInformationTransform(const QTransform &transform); InformationName setInformationContentTransform(const QTransform &contentTransform); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index 1fbea423b38..2566b1e7481 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -26,6 +26,7 @@ public: qint32 parentInstanceId{-1}; ModelNode modelNode; QRectF boundingRect; + QRectF boundingRectPixmap; QRectF contentItemBoundingRect; QPointF position; QSizeF size; @@ -166,9 +167,11 @@ void NodeInstance::makeInvalid() QRectF NodeInstance::boundingRect() const { - if (isValid()) + if (isValid()) { + if (d->boundingRectPixmap.isValid()) + return d->boundingRectPixmap; return d->boundingRect; - else + } else return QRectF(); } @@ -527,6 +530,16 @@ InformationName NodeInstance::setInformationBoundingRect(const QRectF &rectangle return NoInformationChange; } +InformationName NodeInstance::setInformationBoundingRectPixmap(const QRectF &rectangle) +{ + if (d->boundingRectPixmap != rectangle) { + d->boundingRectPixmap = rectangle; + return BoundingRectPixmap; + } + + return NoInformationChange; +} + InformationName NodeInstance::setInformationContentItemBoundingRect(const QRectF &rectangle) { if (d->contentItemBoundingRect != rectangle) { @@ -713,7 +726,10 @@ InformationName NodeInstance::setInformation(InformationName name, const QVarian { switch (name) { case Size: return setInformationSize(information.toSizeF()); - case BoundingRect: return setInformationBoundingRect(information.toRectF()); + case BoundingRect: + return setInformationBoundingRect(information.toRectF()); + case BoundingRectPixmap: + return setInformationBoundingRectPixmap(information.toRectF()); case ContentItemBoundingRect: return setInformationContentItemBoundingRect(information.toRectF()); case Transform: return setInformationTransform(information.value()); case ContentTransform: return setInformationContentTransform(information.value()); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 959388f2c1c..67bbc93a10f 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1480,11 +1480,21 @@ void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command) QSet renderImageChangeSet; + QVector containerVector; + const QVector containers = command.images(); for (const ImageContainer &container : containers) { if (hasInstanceForId(container.instanceId())) { NodeInstance instance = instanceForId(container.instanceId()); if (instance.isValid()) { + if (container.rect().isValid()) { + InformationContainer rectContainer = InformationContainer(container.instanceId(), + BoundingRectPixmap, + container.rect(), + {}, + {}); + containerVector.append(rectContainer); + } instance.setRenderPixmap(container.image()); renderImageChangeSet.insert(instance.modelNode()); } @@ -1495,6 +1505,14 @@ void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command) if (!renderImageChangeSet.isEmpty()) emitInstancesRenderImageChanged(Utils::toList(renderImageChangeSet).toVector()); + + if (!containerVector.isEmpty()) { + QMultiHash informationChangeHash = informationChanged( + containerVector); + + if (!informationChangeHash.isEmpty()) + emitInstanceInformationsChange(informationChangeHash); + } } QMultiHash NodeInstanceView::informationChanged(const QVector &containerVector) diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp index 9fe970f8c7c..d3209e4ccbe 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -1316,7 +1316,9 @@ PixmapChangedCommand NodeInstanceServer::createPixmapChangedCommand(const QList< // item image in case the instance changed from having content to not having content. if (instance.hasContent()) renderImage = instance.renderImage(); - imageVector.append(ImageContainer(instance.instanceId(), renderImage, instance.instanceId())); + auto container = ImageContainer(instance.instanceId(), renderImage, instance.instanceId()); + container.setRect(instance.boundingRect()); + imageVector.append(container); } return PixmapChangedCommand(imageVector);