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 <tim.jenssen@qt.io>
This commit is contained in:
Thomas Hartmann
2022-11-16 14:15:53 +01:00
committed by Tim Jenssen
parent f6cfe31c7f
commit 2a44f8caaf
7 changed files with 65 additions and 13 deletions

View File

@@ -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<qint32> &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) {

View File

@@ -3,8 +3,9 @@
#pragma once
#include <QMetaType>
#include <QImage>
#include <QMetaType>
#include <QRectF>
namespace QmlDesigner {
@@ -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<qint32> &keyNumberVector);
@@ -30,6 +33,7 @@ private:
QImage m_image;
qint32 m_instanceId;
qint32 m_keyNumber;
QRectF m_rect;
};
QDataStream &operator<<(QDataStream &out, const ImageContainer &container);

View File

@@ -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
};
}

View File

@@ -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);

View File

@@ -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<QTransform>());
case ContentTransform: return setInformationContentTransform(information.value<QTransform>());

View File

@@ -1480,11 +1480,21 @@ void NodeInstanceView::pixmapChanged(const PixmapChangedCommand &command)
QSet<ModelNode> renderImageChangeSet;
QVector<InformationContainer> containerVector;
const QVector<ImageContainer> 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<ModelNode, InformationName> informationChangeHash = informationChanged(
containerVector);
if (!informationChangeHash.isEmpty())
emitInstanceInformationsChange(informationChangeHash);
}
}
QMultiHash<ModelNode, InformationName> NodeInstanceView::informationChanged(const QVector<InformationContainer> &containerVector)

View File

@@ -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);