aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quickvectorimage/generator/qquickgenerator_p.h2
-rw-r--r--src/quickvectorimage/generator/qquickqmlgenerator.cpp97
-rw-r--r--src/quickvectorimage/generator/qquickqmlgenerator_p.h4
-rw-r--r--src/quickvectorimage/qquickvectorimage.cpp97
-rw-r--r--src/quickvectorimage/qquickvectorimage_p.h37
-rw-r--r--src/quickvectorimage/qquickvectorimage_p_p.h6
6 files changed, 214 insertions, 29 deletions
diff --git a/src/quickvectorimage/generator/qquickgenerator_p.h b/src/quickvectorimage/generator/qquickgenerator_p.h
index 4ab7671b69..e287a667ef 100644
--- a/src/quickvectorimage/generator/qquickgenerator_p.h
+++ b/src/quickvectorimage/generator/qquickgenerator_p.h
@@ -51,7 +51,7 @@ public:
bool generate();
- virtual void generateNodeBase(const NodeInfo &info) = 0;
+ virtual QString generateNodeBase(const NodeInfo &info) = 0;
virtual bool generateDefsNode(const NodeInfo &info) = 0;
virtual void generateImageNode(const ImageNodeInfo &info) = 0;
virtual void generatePath(const PathNodeInfo &info, const QRectF &overrideBoundingRect = QRectF{}) = 0;
diff --git a/src/quickvectorimage/generator/qquickqmlgenerator.cpp b/src/quickvectorimage/generator/qquickqmlgenerator.cpp
index 2e71b415bd..e7595c315e 100644
--- a/src/quickvectorimage/generator/qquickqmlgenerator.cpp
+++ b/src/quickvectorimage/generator/qquickqmlgenerator.cpp
@@ -77,7 +77,7 @@ QString QQuickQmlGenerator::commentString() const
return m_commentString;
}
-void QQuickQmlGenerator::generateNodeBase(const NodeInfo &info)
+QString QQuickQmlGenerator::generateNodeBase(const NodeInfo &info)
{
if (!info.nodeId.isEmpty())
stream() << "objectName: \"" << info.nodeId << "\"";
@@ -134,6 +134,8 @@ void QQuickQmlGenerator::generateNodeBase(const NodeInfo &info)
if (info.opacity.isAnimated())
generatePropertyAnimation(info.opacity, idString, QStringLiteral("opacity"));
+
+ return idString;
}
bool QQuickQmlGenerator::generateDefsNode(const NodeInfo &info)
@@ -258,16 +260,40 @@ void QQuickQmlGenerator::generateGradient(const QGradient *grad)
}
}
+void QQuickQmlGenerator::generateAnimationBindings()
+{
+ stream() << "loops: " << m_topLevelIdString << ".animations.loops";
+ stream() << "paused: " << m_topLevelIdString << ".animations.paused";
+ stream() << "running: true";
+
+ stream() << "property bool wasRunning: false";
+
+ // We need to reset the animation when the loop count changes
+ stream() << "onLoopsChanged: { if (running) { restart() } }";
+}
+
void QQuickQmlGenerator::generatePropertyAnimation(const QQuickAnimatedProperty &property,
const QString &targetName,
const QString &propertyName,
AnimationType animationType)
{
- if (property.animationCount() > 1) {
- stream() << "ParallelAnimation {";
- m_indentLevel++;
- stream() << "running: true";
- }
+ if (!property.isAnimated())
+ return;
+
+ QString mainAnimationId = targetName
+ + QStringLiteral("_")
+ + propertyName
+ + QStringLiteral("_animation");
+ mainAnimationId.replace(QLatin1Char('.'), QLatin1Char('_'));
+
+ stream() << "Connections { target: " << m_topLevelIdString << ".animations; function onRestart() {" << mainAnimationId << ".restart() } }";
+
+ stream() << "ParallelAnimation {";
+ m_indentLevel++;
+
+ stream() << "id: " << mainAnimationId;
+
+ generateAnimationBindings();
for (int i = 0; i < property.animationCount(); ++i) {
const QQuickAnimatedProperty::PropertyAnimation &animation = property.animation(i);
@@ -275,9 +301,6 @@ void QQuickQmlGenerator::generatePropertyAnimation(const QQuickAnimatedProperty
stream() << "SequentialAnimation {";
m_indentLevel++;
- if (property.animationCount() == 1)
- stream() << "running: true";
-
const int startOffset = animation.startOffset;
if (startOffset > 0)
stream() << "PauseAnimation { duration: " << startOffset << " }";
@@ -354,10 +377,8 @@ void QQuickQmlGenerator::generatePropertyAnimation(const QQuickAnimatedProperty
stream() << "}";
}
- if (property.animationCount() > 1) {
- m_indentLevel--;
- stream() << "}";
- }
+ m_indentLevel--;
+ stream() << "}";
}
void QQuickQmlGenerator::generateTransform(const QTransform &xf)
@@ -649,11 +670,19 @@ void QQuickQmlGenerator::generatePathContainer(const StructureNodeInfo &info)
void QQuickQmlGenerator::generateAnimateTransform(const QString &targetName, const NodeInfo &info)
{
- if (info.transform.animationCount() > 1) {
- stream() << "ParallelAnimation {";
- m_indentLevel++;
- stream() << "running: true";
- }
+ if (!info.transform.isAnimated())
+ return;
+
+ const QString mainAnimationId = targetName
+ + QStringLiteral("_transform_animation");
+ stream() << "Connections { target: " << m_topLevelIdString << ".animations; function onRestart() {" << mainAnimationId << ".restart() } }";
+
+ stream() << "ParallelAnimation {";
+ m_indentLevel++;
+
+ stream() << "id:" << mainAnimationId;
+
+ generateAnimationBindings();
for (int i = 0; i < info.transform.animationCount(); ++i) {
const QQuickAnimatedProperty::PropertyAnimation &animation = info.transform.animation(i);
@@ -661,9 +690,6 @@ void QQuickQmlGenerator::generateAnimateTransform(const QString &targetName, con
stream() << "SequentialAnimation {";
m_indentLevel++;
- if (info.transform.animationCount() == 1)
- stream() << "running: true";
-
const int startOffset = animation.startOffset;
if (startOffset > 0)
stream() << "PauseAnimation { duration: " << startOffset << " }";
@@ -838,10 +864,8 @@ void QQuickQmlGenerator::generateAnimateTransform(const QString &targetName, con
stream() << "}";
}
- if (info.transform.animationCount() > 1) {
- m_indentLevel--;
- stream() << "}";
- }
+ m_indentLevel--;
+ stream() << "}";
}
bool QQuickQmlGenerator::generateStructureNode(const StructureNodeInfo &info)
@@ -924,6 +948,7 @@ bool QQuickQmlGenerator::generateRootNode(const StructureNodeInfo &info)
stream() << "// " << comment;
stream() << "import QtQuick";
+ stream() << "import QtQuick.VectorImage";
stream() << "import QtQuick.VectorImage.Helpers";
stream() << "import QtQuick.Shapes" << Qt::endl;
stream() << "Item {";
@@ -936,6 +961,19 @@ bool QQuickQmlGenerator::generateRootNode(const StructureNodeInfo &info)
if (h > 0)
stream() << "implicitHeight: " << h;
+ stream() << "component AnimationsInfo : QtObject";
+ stream() << "{";
+ m_indentLevel++;
+
+ stream() << "property bool paused: false";
+ stream() << "property int loops: 1";
+ stream() << "signal restart()";
+
+ m_indentLevel--;
+ stream() << "}";
+
+ stream() << "property AnimationsInfo animations : AnimationsInfo {}";
+
if (!info.viewBox.isEmpty()) {
stream() << "transform: [";
m_indentLevel++;
@@ -948,11 +986,16 @@ bool QQuickQmlGenerator::generateRootNode(const StructureNodeInfo &info)
}
if (!info.forceSeparatePaths && info.isPathContainer) {
+ m_topLevelIdString = QStringLiteral("__qt_toplevel");
+ stream() << "id: " << m_topLevelIdString;
+
generatePathContainer(info);
m_indentLevel++;
- }
- generateNodeBase(info);
+ generateNodeBase(info);
+ } else {
+ m_topLevelIdString = generateNodeBase(info);
+ }
} else {
if (m_inShapeItemLevel > 0) {
m_inShapeItemLevel--;
diff --git a/src/quickvectorimage/generator/qquickqmlgenerator_p.h b/src/quickvectorimage/generator/qquickqmlgenerator_p.h
index d65bd4ccc5..63590365a7 100644
--- a/src/quickvectorimage/generator/qquickqmlgenerator_p.h
+++ b/src/quickvectorimage/generator/qquickqmlgenerator_p.h
@@ -80,7 +80,7 @@ public:
}
protected:
- void generateNodeBase(const NodeInfo &info) override;
+ QString generateNodeBase(const NodeInfo &info) override;
bool generateDefsNode(const NodeInfo &info) override;
void generateImageNode(const ImageNodeInfo &info) override;
void generatePath(const PathNodeInfo &info, const QRectF &overrideBoundingRect) override;
@@ -96,6 +96,7 @@ private:
void generateTransform(const QTransform &xf);
void generatePathContainer(const StructureNodeInfo &info);
void generateAnimateTransform(const QString &targetName, const NodeInfo &info);
+ void generateAnimationBindings();
enum class AnimationType {
Auto = 0,
@@ -126,6 +127,7 @@ private:
QString m_assetFileDirectory;
QString m_assetFilePrefix;
QString m_urlPrefix;
+ QString m_topLevelIdString;
};
QT_END_NAMESPACE
diff --git a/src/quickvectorimage/qquickvectorimage.cpp b/src/quickvectorimage/qquickvectorimage.cpp
index 614514c393..f4cde81e21 100644
--- a/src/quickvectorimage/qquickvectorimage.cpp
+++ b/src/quickvectorimage/qquickvectorimage.cpp
@@ -79,6 +79,7 @@ void QQuickVectorImagePrivate::loadSvg()
q->setImplicitWidth(svgItem->width());
q->setImplicitHeight(svgItem->height());
+ q->updateAnimationProperties();
q->updateSvgItemScale();
q->update();
}
@@ -186,6 +187,35 @@ void QQuickVectorImage::updateSvgItemScale()
}
}
+void QQuickVectorImage::updateAnimationProperties()
+{
+ Q_D(QQuickVectorImage);
+ if (Q_UNLIKELY(d->svgItem == nullptr || d->svgItem->childItems().isEmpty()))
+ return;
+
+ QQuickItem *childItem = d->svgItem->childItems().first();
+ if (Q_UNLIKELY(d->animations != nullptr)) {
+ QObject *animationsInfo = childItem->property("animations").value<QObject*>();
+ if (Q_UNLIKELY(animationsInfo != nullptr)) {
+ animationsInfo->setProperty("loops", d->animations->loops());
+ animationsInfo->setProperty("paused", d->animations->paused());
+ }
+ }
+}
+
+QQuickVectorImageAnimations *QQuickVectorImage::animations()
+{
+ Q_D(QQuickVectorImage);
+ if (d->animations == nullptr) {
+ d->animations = new QQuickVectorImageAnimations;
+ QQml_setParent_noEvent(d->animations, this);
+ QObject::connect(d->animations, &QQuickVectorImageAnimations::loopsChanged, this, &QQuickVectorImage::updateAnimationProperties);
+ QObject::connect(d->animations, &QQuickVectorImageAnimations::pausedChanged, this, &QQuickVectorImage::updateAnimationProperties);
+ }
+
+ return d->animations;
+}
+
/*!
\qmlproperty enumeration QtQuick.VectorImage::VectorImage::fillMode
@@ -252,6 +282,73 @@ void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRender
emit preferredRendererTypeChanged();
}
+/*!
+ \qmlpropertygroup QtQuick.VectorImage::VectorImage::animations
+ \qmlproperty bool QtQuick.VectorImage::VectorImage::animations.paused
+ \qmlproperty int QtQuick.VectorImage::VectorImage::animations.loops
+ \since 6.10
+
+ These properties can be used to control animations in the image, if it contains any.
+
+ The \c paused property can be set to true to temporarily pause all animations. When the
+ property is reset to \c false, the animations will resume where they were. By default this
+ property is \c false.
+
+ The \c loops property defines the number of times the animations in the document will repeat.
+ By default this property is 1. Any animations that is set to loop indefinitely in the source
+ image will be unaffected by this property. To make all animations in the document repeat
+ indefinitely, the \c loops property can be set to \c{Animation.Infinite}.
+*/
+int QQuickVectorImageAnimations::loops() const
+{
+ return m_loops;
+}
+
+void QQuickVectorImageAnimations::setLoops(int loops)
+{
+ if (m_loops == loops)
+ return;
+ m_loops = loops;
+ emit loopsChanged();
+}
+
+bool QQuickVectorImageAnimations::paused() const
+{
+ return m_paused;
+}
+
+void QQuickVectorImageAnimations::setPaused(bool paused)
+{
+ if (m_paused == paused)
+ return;
+ m_paused = paused;
+ emit pausedChanged();
+}
+
+void QQuickVectorImageAnimations::restart()
+{
+ QQuickVectorImage *parentVectorImage = qobject_cast<QQuickVectorImage *>(parent());
+ if (Q_UNLIKELY(parentVectorImage == nullptr)) {
+ qCWarning(lcQuickVectorImage) << Q_FUNC_INFO << "Parent is not a VectorImage";
+ return;
+ }
+
+ QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
+
+ if (Q_UNLIKELY(d->svgItem == nullptr || d->svgItem->childItems().isEmpty()))
+ return;
+
+ QQuickItem *childItem = d->svgItem->childItems().first();
+ QObject *animationsInfo = childItem->property("animations").value<QObject*>();
+
+ if (Q_UNLIKELY(animationsInfo == nullptr)) {
+ qCWarning(lcQuickVectorImage) << Q_FUNC_INFO << "Item does not have animations property";
+ return;
+ }
+
+ QMetaObject::invokeMethod(animationsInfo, "restart");
+}
+
QT_END_NAMESPACE
#include <moc_qquickvectorimage_p.cpp>
diff --git a/src/quickvectorimage/qquickvectorimage_p.h b/src/quickvectorimage/qquickvectorimage_p.h
index cce935d3ea..a997f2e8ba 100644
--- a/src/quickvectorimage/qquickvectorimage_p.h
+++ b/src/quickvectorimage/qquickvectorimage_p.h
@@ -16,11 +16,13 @@
//
#include <QQuickItem>
+#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuickVectorImage/qtquickvectorimageexports.h>
QT_BEGIN_NAMESPACE
class QQuickVectorImagePrivate;
+class QQuickVectorImageAnimations;
class Q_QUICKVECTORIMAGE_EXPORT QQuickVectorImage : public QQuickItem
{
@@ -29,6 +31,7 @@ class Q_QUICKVECTORIMAGE_EXPORT QQuickVectorImage : public QQuickItem
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged)
Q_PROPERTY(RendererType preferredRendererType READ preferredRendererType WRITE setPreferredRendererType NOTIFY preferredRendererTypeChanged)
+ Q_PROPERTY(QQuickVectorImageAnimations *animations READ animations CONSTANT REVISION(6, 10) FINAL)
QML_NAMED_ELEMENT(VectorImage)
public:
@@ -57,6 +60,8 @@ public:
RendererType preferredRendererType() const;
void setPreferredRendererType(RendererType newPreferredRendererType);
+ QQuickVectorImageAnimations *animations();
+
signals:
void sourceChanged();
void fillModeChanged();
@@ -65,12 +70,44 @@ signals:
private slots:
void updateSvgItemScale();
+ void updateAnimationProperties();
private:
Q_DISABLE_COPY(QQuickVectorImage)
Q_DECLARE_PRIVATE(QQuickVectorImage)
};
+class Q_QUICKVECTORIMAGE_EXPORT QQuickVectorImageAnimations : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged FINAL)
+ Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged FINAL)
+
+ QML_ANONYMOUS
+ QML_ADDED_IN_VERSION(6, 10)
+public:
+ QQuickVectorImageAnimations(QObject *parent = nullptr) : QObject(parent) {}
+
+ int loops() const;
+
+ void setLoops(int loops);
+
+ bool paused() const;
+ void setPaused(bool paused);
+
+ Q_INVOKABLE void restart();
+
+Q_SIGNALS:
+ void loopsChanged();
+ void enabledChanged();
+ void pausedChanged();
+
+private:
+ int m_loops = 1;
+ bool m_paused = false;
+};
+
QT_END_NAMESPACE
#endif // QQUICKVECTORIMAGE_P_H
diff --git a/src/quickvectorimage/qquickvectorimage_p_p.h b/src/quickvectorimage/qquickvectorimage_p_p.h
index 4ad408b628..0114d611a9 100644
--- a/src/quickvectorimage/qquickvectorimage_p_p.h
+++ b/src/quickvectorimage/qquickvectorimage_p_p.h
@@ -32,6 +32,11 @@ public:
void setSource(const QUrl &source);
void loadSvg();
+ static QQuickVectorImagePrivate *get(QQuickVectorImage *q)
+ {
+ return q->d_func();
+ }
+
enum Format {
Unknown,
Svg
@@ -42,6 +47,7 @@ public:
QQuickItem *svgItem = nullptr;
QQuickVectorImage::FillMode fillMode = QQuickVectorImage::Stretch;
QQuickVectorImage::RendererType preferredRendererType = QQuickVectorImage::GeometryRenderer;
+ QQuickVectorImageAnimations *animations = nullptr;
};
QT_END_NAMESPACE