Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickvectorimage.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qurl.h>
5#include <QtCore/QScopeGuard>
11#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
12#include <QtQuickVectorImageGenerator/private/qquickasyncitembuilder_p.h>
13#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
14#include <QtQuickVectorImageGenerator/private/qquickanimationrootitem_p.h>
15#include <QtCore/private/qfactoryloader_p.h>
16#include <QtCore/qloggingcategory.h>
17
18#include <private/qquicktranslate_p.h>
19#include <private/qquickanimation_p.h>
20
21QT_BEGIN_NAMESPACE
22
23using namespace Qt::StringLiterals;
24
25Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, itemGenPluginLoader,
27 QLatin1String("/vectorimageformats"), Qt::CaseInsensitive))
28
29bool QQuickVectorImagePrivate::useQmlGenerator()
30{
31 Q_Q(QQuickVectorImage);
32 static const bool val = qEnvironmentVariableIsSet("QT_QUICKVECTORIMAGE_USE_QML_GENERATOR");
33 const bool useNonDefaultGenerator = q->property("_qt_usenondefaultgenerator").toBool();
34 return useNonDefaultGenerator ? !val : val;
35}
36
38createPluginGenerators(const QQuickVectorImageSource &source,
39 QQuickVectorImageGenerator::GeneratorFlags flags)
40{
41 std::vector<std::unique_ptr<QQuickVectorImagePluginGenerator>> ret;
42 if (!flags.testFlag(QQuickVectorImageGenerator::AssumeTrustedSource))
43 return ret;
44
45 QFactoryLoader *loader = itemGenPluginLoader();
46 const qsizetype count = loader->keyMap().size();
47 for (qsizetype i = 0; i < count; ++i) {
48 QQuickVectorImagePlugin *plugin =
49 qobject_cast<QQuickVectorImagePlugin *>(loader->instance(i));
50 if (plugin != nullptr) {
51 std::unique_ptr<QQuickVectorImagePluginGenerator> pluginGen(
52 plugin->createGenerator(source));
53 if (pluginGen != nullptr)
54 ret.push_back(std::move(pluginGen));
55 }
56 }
57
58 return ret;
59}
60
61/*!
62 \qmlmodule QtQuick.VectorImage
63 \title Qt Quick Vector Image QML Types
64 \ingroup qmlmodules
65 \brief Provides QML types for displaying vector image files.
66 \since 6.8
67
68 To use the types in this module, import the module with the following line:
69
70 \qml
71 import QtQuick.VectorImage
72 \endqml
73
74 Qt Quick Vector Image provides support for displaying vector image files in a Qt Quick
75 scene.
76
77 It currently supports the \c SVG file format. In addition, Lottie support
78 can be enabled by setting the
79 \l{QtQuick.VectorImage::VectorImage::}{assumeTrustedSource} property to true
80 and including the plugin from the \l{Qt Lottie Animation} module.
81
82 Qt supports multiple options for displaying SVG files. For an overview and comparison of
83 the different ones, see the documentation of the \l{svgtoqml} tool.
84
85 \section1 QML Types
86*/
87
88void QQuickVectorImagePrivate::setSource(const QUrl &source)
89{
90 Q_Q(QQuickVectorImage);
91 if (imageSource.source() == source)
92 return;
93
94 imageSource.setSource(source);
95 loadFile();
96 emit q->sourceChanged();
97}
98
99void QQuickVectorImagePrivate::setSourceData(const QByteArray &data)
100{
101 imageSource.setData(data);
102 loadFile();
103}
104
105// Stops a running asynchronous build of the item tree without waiting for the worker thread.
106// Returns true if a build was cancelled.
107bool QQuickVectorImagePrivate::cancelAsyncBuilder()
108{
109 Q_Q(QQuickVectorImage);
110 if (asyncBuilder == nullptr)
111 return false;
112
113 asyncBuilder->disconnect(q);
114 asyncBuilder->cancel();
115 asyncBuilder->deleteLater();
116 asyncBuilder = nullptr;
117 return true;
118}
119
120void QQuickVectorImagePrivate::loadFile()
121{
122 Q_Q(QQuickVectorImage);
123
124 if (!q->isComponentComplete())
125 return;
126
127 QQmlContext *ctx = qmlContext(q);
128 imageSource.resolveLocalFileName(ctx);
129
130 const bool asyncBuilderCancelled = cancelAsyncBuilder();
131 const bool startsAsyncBuilder = !useQmlGenerator() && asynchronous && !imageSource.isEmpty();
132
133 if (rootItem && (!retainWhileLoading || imageSource.isEmpty())) {
134 rootItem->deleteLater();
135 rootItem = nullptr;
136 emit q->generatedItemChanged();
137 // When starting the async builder, the status goes directly to Loading below
138 if (incubator == nullptr && !startsAsyncBuilder)
139 emit q->statusChanged();
140 } else if (asyncBuilderCancelled && imageSource.isEmpty()) {
141 emit q->statusChanged();
142 }
143
144 if (imageSource.isEmpty())
145 return;
146
147 if (incubator != nullptr) {
148 // If the incubator is still alive, it means it was interrupted before we could add the
149 // object to the parent item.
150 QObject *obj = incubator->object();
151 delete obj;
152
153 incubator->disconnect(q);
154 incubator->deleteLater();
155 }
156
157 if (pendingRootItem != nullptr) {
158 delete pendingRootItem;
159 pendingRootItem = nullptr;
160 }
161
162 QQuickVectorImageGenerator::GeneratorFlags flags;
163 if (preferredRendererType == QQuickVectorImage::CurveRenderer)
164 flags.setFlag(QQuickVectorImageGenerator::CurveRenderer);
165 if (assumeTrustedSource)
166 flags.setFlag(QQuickVectorImageGenerator::AssumeTrustedSource);
167 if (m_asyncShapes)
168 flags.setFlag(QQuickVectorImageGenerator::AsyncShapes);
169 if (asynchronous)
170 flags.setFlag(QQuickVectorImageGenerator::AsynchronousLoading);
171
172 if (useQmlGenerator()) {
173 QQmlIncubator::IncubationMode mode =
174 asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous;
175
176 if (!context || context->engine() != qmlContext(q)->engine())
177 context.reset(new QQmlContext(qmlContext(q)->engine()));
178
179 incubator = new QQuickVectorImageIncubator(mode, context.get(), q);
180 QObject::connect(incubator, &QQuickVectorImageIncubator::statusUpdated, q,
181 &QQuickVectorImage::updateItem);
182 incubator->start(imageSource, flags);
183 } else if (startsAsyncBuilder) {
184 asyncBuilder = new QQuickAsyncItemBuilder(imageSource, flags, qmlContext(q), q);
185 QObject::connect(asyncBuilder, &QQuickAsyncItemBuilder::finished, q,
186 &QQuickVectorImage::updateItem);
187 asyncBuilder->start(createPluginGenerators(imageSource, flags));
188 emit q->statusChanged();
189 } else {
190 QQuickItemGenerator gen(imageSource, flags, qmlContext(q));
191
192 bool generatedWithPlugin = false;
193 const auto pluginGenerators = createPluginGenerators(imageSource, flags);
194 for (const auto &pluginGen : pluginGenerators) {
195 if ((generatedWithPlugin = pluginGen->generate(&gen)))
196 break;
197 }
198
199 if (!generatedWithPlugin)
200 gen.generate();
201
202 if (gen.errorState() != QQuickVectorImageGenerator::NoError) {
203 qCWarning(lcQuickVectorImage)
204 << "QQuickItemGenerator: failed to generate" << imageSource
205 << "(errorState:" << gen.errorState() << ")";
206 } else {
207 pendingRootItem = gen.takeRootItem();
208 }
209 q->updateItem();
210 }
211}
212
213void QQuickVectorImage::updateItem()
214{
215 Q_D(QQuickVectorImage);
216
217 const QQuickItem *oldGenItem = generatedItem();
218 auto emitter = qScopeGuard([&] { // emit at any function exit
219 if (generatedItem() != oldGenItem)
220 emit generatedItemChanged();
221 emit statusChanged();
222 });
223
224 QQuickItem *item = nullptr;
225 if (d->incubator != nullptr) {
226 if (d->incubator->object() == nullptr || !d->incubator->isReady())
227 return;
228 item = qobject_cast<QQuickItem *>(d->incubator->object());
229 if (item == nullptr) {
230 qCWarning(lcQuickVectorImage)
231 << "QQuickVectorImage::updateItem: Root item not a QQuickItem:"
232 << d->incubator->errors();
233 return;
234 }
235 } else if (d->asyncBuilder != nullptr) {
236 if (d->asyncBuilder->state() != QQuickAsyncItemBuilder::State::Finished)
237 return;
238 item = d->asyncBuilder->takeRootItem();
239 d->asyncBuilder->disconnect(this);
240 d->asyncBuilder->deleteLater(); // We are called from within the builder
241 d->asyncBuilder = nullptr;
242 if (item == nullptr)
243 return;
244 } else {
245 item = d->pendingRootItem;
246 d->pendingRootItem = nullptr;
247 if (item == nullptr)
248 return;
249 }
250
251 if (d->rootItem != nullptr)
252 d->rootItem->deleteLater();
253
254 d->rootItem = new QQuickItem(this);
255 d->rootItem->setParentItem(this);
256 d->rootItem->setImplicitWidth(item->width());
257 d->rootItem->setImplicitHeight(item->height());
258
259 item->setParent(d->rootItem);
260 item->setParentItem(d->rootItem);
261
262 setImplicitWidth(d->rootItem->width());
263 setImplicitHeight(d->rootItem->height());
264
265 updateAnimationProperties();
266 updateRootItemScale();
267 update();
268
269 static int freezeTime = qEnvironmentVariableIntValue("QT_QUICKVECTORIMAGE_FREEZE");
270 if (freezeTime != 0) {
271 if (freezeTime < 0)
272 freezeTime = 400; // TBD: calculate better default, e.g. midtime of total anim duration
273 animations()->setPaused(true);
274 const QList<QQuickAbstractAnimation *> anims = d->rootItem->findChildren<QQuickAbstractAnimation *>();
275 for (QQuickAbstractAnimation *anim : anims) {
276 if (anim->group() == nullptr)
277 anim->setCurrentTime(freezeTime);
278 }
279 }
280
281 if (d->incubator) {
282 QQuickVectorImageIncubatorPrivate *dd = QQuickVectorImageIncubatorPrivate::get(d->incubator);
283 auto componentGuard = dd->takeComponentGuard();
284 if (!componentGuard.isNull()) {
285 Q_ASSERT(componentGuard.component() == nullptr);
286 connect(d->rootItem, &QObject::destroyed, d->rootItem,
287 [componentGuard = std::move(componentGuard)]() {
288 // componentGuard cleans up when it goes out of scope
289 Q_UNUSED(componentGuard);
290 });
291 }
292
293 d->incubator->disconnect(this);
294 d->incubator->deleteLater();
295 d->incubator = nullptr;
296 }
297}
298
299/*!
300 \qmltype VectorImage
301 \inqmlmodule QtQuick.VectorImage
302 \inherits Item
303 \brief Loads a vector image file and displays it in a Qt Quick scene.
304 \since 6.8
305
306 The VectorImage can be used to load a vector image file and display this as an item in a Qt
307 Quick scene.
308
309 It currently supports the \c SVG file format. In addition, Lottie support can be enabled by
310 setting the \l{assumeTrustedSource} property to true and including the plugin from the
311 \l{Qt Lottie Animation} module.
312
313 \note This complements the approach of loading the vector image file through an \l Image
314 element: \l Image creates a raster version of the image at the requested size. VectorImage
315 builds a Qt Quick scene that represents the image. This means the resulting item can be scaled
316 and rotated without losing quality, and it will typically consume less memory than the
317 rasterized version.
318*/
319QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
320 : QQuickItem(*(new QQuickVectorImagePrivate), parent)
321{
322 setFlag(QQuickItem::ItemHasContents, true);
323
324 QObject::connect(this, &QQuickItem::widthChanged, this, &QQuickVectorImage::updateRootItemScale);
325 QObject::connect(this, &QQuickItem::heightChanged, this, &QQuickVectorImage::updateRootItemScale);
326 QObject::connect(this, &QQuickVectorImage::fillModeChanged, this, &QQuickVectorImage::updateRootItemScale);
327}
328
329QQuickVectorImage::~QQuickVectorImage()
330{
331 Q_D(QQuickVectorImage);
332 // This may have a running thread, so we need to delete it before we start deleting children
333 delete d->incubator;
334 d->incubator = nullptr;
335
336 // Does not wait for the worker thread
337 delete d->asyncBuilder;
338 d->asyncBuilder = nullptr;
339}
340
341/*!
342 \qmlproperty url QtQuick.VectorImage::VectorImage::source
343
344 This property holds the URL of the vector image file to load.
345
346 VectorImage currently supports the \c SVG file format. In addition, Lottie support can be
347 enabled by setting the \l{assumeTrustedSource} property to true and including the plugin from
348 the \l{Qt Lottie Animation} module.
349*/
350QUrl QQuickVectorImage::source() const
351{
352 Q_D(const QQuickVectorImage);
353 return d->imageSource.source();
354}
355
356void QQuickVectorImage::setSource(const QUrl &source)
357{
358 Q_D(QQuickVectorImage);
359 d->setSource(source);
360}
361
362void QQuickVectorImage::updateRootItemScale()
363{
364 Q_D(QQuickVectorImage);
365
366 if (d->rootItem == nullptr
367 || qFuzzyIsNull(d->rootItem->width())
368 || qFuzzyIsNull(d->rootItem->height())) {
369 return;
370 }
371
372 auto xformProp = d->rootItem->transform();
373 QQuickScale *scaleTransform = nullptr;
374 if (xformProp.count(&xformProp) == 0) {
375 scaleTransform = new QQuickScale;
376 scaleTransform->setParent(d->rootItem);
377 xformProp.append(&xformProp, scaleTransform);
378 } else {
379 scaleTransform = qobject_cast<QQuickScale *>(xformProp.at(&xformProp, 0));
380 }
381
382 if (scaleTransform != nullptr) {
383 qreal xScale = width() / d->rootItem->width();
384 qreal yScale = height() / d->rootItem->height();
385
386 switch (d->fillMode) {
387 case QQuickVectorImage::NoResize:
388 xScale = yScale = 1.0;
389 break;
390 case QQuickVectorImage::PreserveAspectFit:
391 xScale = yScale = qMin(xScale, yScale);
392 break;
393 case QQuickVectorImage::PreserveAspectCrop:
394 xScale = yScale = qMax(xScale, yScale);
395 break;
396 case QQuickVectorImage::Stretch:
397 // Already correct
398 break;
399 };
400
401 scaleTransform->setXScale(xScale);
402 scaleTransform->setYScale(yScale);
403 }
404}
405
406void QQuickVectorImage::updateAnimationProperties()
407{
408 Q_D(QQuickVectorImage);
409 if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
410 return;
411
412 QQuickItem *childItem = d->rootItem->childItems().first();
413 if (Q_LIKELY(d->animations != nullptr)) {
414 if (auto *root = qobject_cast<QQuickAnimationRootItem *>(childItem)) {
415 root->setLoops(d->animations->loops());
416 root->setPaused(d->animations->paused());
417 } else {
418 childItem->setProperty("loops", d->animations->loops());
419 childItem->setProperty("paused", d->animations->paused());
420 }
421 }
422}
423
424QQuickVectorImageAnimations *QQuickVectorImage::animations()
425{
426 Q_D(QQuickVectorImage);
427 if (d->animations == nullptr) {
428 d->animations = new QQuickVectorImageAnimations;
429 QQml_setParent_noEvent(d->animations, this);
430 QObject::connect(d->animations, &QQuickVectorImageAnimations::loopsChanged, this, &QQuickVectorImage::updateAnimationProperties);
431 QObject::connect(d->animations, &QQuickVectorImageAnimations::pausedChanged, this, &QQuickVectorImage::updateAnimationProperties);
432 }
433
434 return d->animations;
435}
436
437/*!
438 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::fillMode
439
440 This property defines what happens if the width and height of the VectorImage differs from
441 the implicit size of its contents.
442
443 \value VectorImage.NoResize The contents are still rendered at the size provided by
444 the input.
445 \value VectorImage.Stretch The contents are scaled to match the width and height of
446 the \c{VectorImage}. (This is the default.)
447 \value VectorImage.PreserveAspectFit The contents are scaled to fit inside the bounds of the
448 \c VectorImage, while preserving aspect ratio. The
449 actual bounding rect of the contents will sometimes be
450 smaller than the \c VectorImage item.
451 \value VectorImage.PreserveAspectCrop The contents are scaled to fill the \c VectorImage item,
452 while preserving the aspect ratio. The actual bounds of
453 the contents will sometimes be larger than the
454 \c VectorImage item.
455*/
456
457QQuickVectorImage::FillMode QQuickVectorImage::fillMode() const
458{
459 Q_D(const QQuickVectorImage);
460 return d->fillMode;
461}
462
463void QQuickVectorImage::setFillMode(FillMode newFillMode)
464{
465 Q_D(QQuickVectorImage);
466 if (d->fillMode == newFillMode)
467 return;
468 d->fillMode = newFillMode;
469 emit fillModeChanged();
470}
471
472/*!
473 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::preferredRendererType
474
475 Requests a specific backend to use for rendering shapes in the \c VectorImage.
476
477 \value VectorImage.GeometryRenderer Equivalent to Shape.GeometryRenderer. This backend flattens
478 curves and triangulates the result. It will give aliased results unless multi-sampling is
479 enabled, and curve flattening may be visible when the item is scaled.
480 \value VectorImage.CurveRenderer Equivalent to Shape.CurveRenderer. With this backend, curves
481 are rendered on the GPU and anti-aliasing is built in. Will typically give better visual
482 results, but at some extra cost to performance.
483
484 The default is \c{VectorImage.GeometryRenderer}.
485*/
486
487QQuickVectorImage::RendererType QQuickVectorImage::preferredRendererType() const
488{
489 Q_D(const QQuickVectorImage);
490 return d->preferredRendererType;
491}
492
493void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRendererType)
494{
495 Q_D(QQuickVectorImage);
496 if (d->preferredRendererType == newPreferredRendererType)
497 return;
498 d->preferredRendererType = newPreferredRendererType;
499 d->loadFile();
500 emit preferredRendererTypeChanged();
501}
502
503/*!
504 \qmlproperty bool QtQuick.VectorImage::VectorImage::asynchronousShapes
505 \since 6.11
506
507 This property controls the {QtQuick.Shapes::Shape::asynchronous}{asynchronous} property of the
508 \l Shape items in the Quick scene that VectorImage builds to represent the image.
509
510 Setting this property to \c true will offload the CPU part of the rendering processing of the
511 shapes to separate worker threads. This can improve CPU utilization and user interface
512 responsiveness.
513
514 By default this property is \c false.
515
516 \sa asynchronous
517*/
518
519bool QQuickVectorImage::asynchronousShapes() const
520{
521 Q_D(const QQuickVectorImage);
522 return d->m_asyncShapes;
523}
524
525void QQuickVectorImage::setAsynchronousShapes(bool asynchronous)
526{
527 Q_D(QQuickVectorImage);
528 if (d->m_asyncShapes == asynchronous)
529 return;
530 d->m_asyncShapes = asynchronous;
531 emit asynchronousShapesChanged();
532}
533
534/*!
535 \qmlproperty bool QtQuick.VectorImage::VectorImage::asynchronous
536 \since 6.12
537
538 This property holds whether the image will be loaded asynchronously. When set to to \c true,
539 the UI will remain reactive while the image is loading. The \l status property can be used
540 to check the current progress.
541
542 By default this property is \c false.
543
544 \sa asynchronousShapes, status
545*/
546
547bool QQuickVectorImage::asynchronous() const
548{
549 Q_D(const QQuickVectorImage);
550 return d->asynchronous;
551}
552
553void QQuickVectorImage::setAsynchronous(bool asynchronous)
554{
555 Q_D(QQuickVectorImage);
556 if (d->asynchronous == asynchronous)
557 return;
558 d->asynchronous = asynchronous;
559 emit asynchronousChanged();
560}
561
562/*!
563 \qmlproperty bool QtQuick.VectorImage::VectorImage::retainWhileLoading
564 \since 6.12
565
566 This property defines the behavior when the \l source property is changed and loading happens
567 asynchronously. This is the case when the \l asynchronous property is set to \c true.
568
569 If \c retainWhileLoading is \c false (the default), the old image is discarded immediately, and
570 the component is cleared while the new image is being loaded. If set to \c true, the old image
571 is retained and remains visible until the new one is ready.
572
573 Enabling this property can avoid flickering in cases where loading the new image takes a long
574 time. It comes at the cost of some extra memory use while the new image is being loaded.
575
576 \sa asynchronous
577*/
578bool QQuickVectorImage::retainWhileLoading() const
579{
580 Q_D(const QQuickVectorImage);
581 return d->retainWhileLoading;
582}
583
584void QQuickVectorImage::setRetainWhileLoading(bool retainWhileLoading)
585{
586 Q_D(QQuickVectorImage);
587 if (d->retainWhileLoading == retainWhileLoading)
588 return;
589 d->retainWhileLoading = retainWhileLoading;
590 emit retainWhileLoadingChanged();
591}
592
593/*!
594 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::status
595 \since 6.12
596
597 This property holds the status of vector image loading. It can be one of:
598
599 \value VectorImage.Null No vector image has been set
600 \value VectorImage.Ready The vector image has been loaded
601 \value VectorImage.Loading The vector image is currently being loaded
602 \value VectorImage.Error An error occurred while loading the vector image
603*/
604QQuickVectorImage::Status QQuickVectorImage::status() const
605{
606 Q_D(const QQuickVectorImage);
607 if (d->asyncBuilder != nullptr) // Only kept while generation is running
608 return Status::Loading;
609
610 if (d->incubator == nullptr) {
611 if (d->rootItem != nullptr)
612 return Status::Ready;
613 else if (!isComponentComplete() || d->imageSource.isEmpty())
614 return Status::Null;
615 else
616 return Status::Error;
617 }
618
619 switch (d->incubator->status()) {
620 case QQmlIncubator::Null:
621 return Status::Null;
622 case QQmlIncubator::Loading:
623 return Status::Loading;
624 case QQmlIncubator::Error:
625 return Status::Error;
626 case QQmlIncubator::Ready:
627 return Status::Ready;
628 };
629
630 return Status::Error;
631}
632
633/*!
634 \qmlproperty bool QtQuick.VectorImage::VectorImage::assumeTrustedSource
635 \since 6.10
636
637 Setting this to true when loading trusted source files expands support for some features that
638 may be unsafe in an uncontrolled setting. For SVG in particular, this maps to the
639 \l{QtSvg::Option}{AssumeTrustedSource option}.
640
641 When this is set to true, VectorImage will also try to load the image using the Lottie format
642 plugin if this is available. See \l{Qt Lottie Animation} for additional information.
643
644 By default this property is \c false.
645
646 \sa svgtoqml, lottietoqml
647 */
648
649bool QQuickVectorImage::assumeTrustedSource() const
650{
651 Q_D(const QQuickVectorImage);
652 return d->assumeTrustedSource;
653}
654
655void QQuickVectorImage::setAssumeTrustedSource(bool assumeTrustedSource)
656{
657 Q_D(QQuickVectorImage);
658 if (d->assumeTrustedSource == assumeTrustedSource)
659 return;
660 d->assumeTrustedSource = assumeTrustedSource;
661 d->loadFile();
662 emit assumeTrustedSourceChanged();
663}
664
665/*!
666 \qmlproperty Item QtQuick.VectorImage::VectorImage::generatedItem
667 \since 6.12
668 \readonly
669
670 When a vector image file is loaded, this property holds the top level Item of the generated Qt
671 Quick scene. When no file is loaded, this property is \c null.
672*/
673
674QQuickItem *QQuickVectorImage::generatedItem() const
675{
676 Q_D(const QQuickVectorImage);
677 return d->rootItem ? d->rootItem->childItems().value(0) : nullptr;
678}
679
680void QQuickVectorImage::componentComplete()
681{
682 Q_D(QQuickVectorImage);
683 QQuickItem::componentComplete();
684
685 d->loadFile();
686}
687
688/*!
689 \qmlpropertygroup QtQuick.VectorImage::VectorImage::animations
690 \qmlproperty bool QtQuick.VectorImage::VectorImage::animations.paused
691 \qmlproperty int QtQuick.VectorImage::VectorImage::animations.loops
692 \since 6.10
693
694 These properties can be used to control animations in the image, if it contains any.
695
696 The \c paused property can be set to true to temporarily pause all animations. When the
697 property is reset to \c false, the animations will resume where they were. By default this
698 property is \c false.
699
700 The \c loops property defines the number of times the animations in the document will repeat.
701 By default this property is 1. Any animations that is set to loop indefinitely in the source
702 image will be unaffected by this property. To make all animations in the document repeat
703 indefinitely, the \c loops property can be set to \c{Animation.Infinite}.
704*/
705int QQuickVectorImageAnimations::loops() const
706{
707 return m_loops;
708}
709
710void QQuickVectorImageAnimations::setLoops(int loops)
711{
712 if (m_loops == loops)
713 return;
714 m_loops = loops;
715 emit loopsChanged();
716}
717
718bool QQuickVectorImageAnimations::paused() const
719{
720 return m_paused;
721}
722
723void QQuickVectorImageAnimations::setPaused(bool paused)
724{
725 if (m_paused == paused)
726 return;
727 m_paused = paused;
728 emit pausedChanged();
729}
730
731void QQuickVectorImageAnimations::restart()
732{
733 QQuickVectorImage *parentVectorImage = qobject_cast<QQuickVectorImage *>(parent());
734 if (Q_UNLIKELY(parentVectorImage == nullptr)) {
735 qCWarning(lcQuickVectorImage) << Q_FUNC_INFO << "Parent is not a VectorImage";
736 return;
737 }
738
739 QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
740
741 if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
742 return;
743
744 QQuickItem *childItem = d->rootItem->childItems().first();
745 QMetaObject::invokeMethod(childItem, "restart");
746}
747
748QT_END_NAMESPACE
749
750#include <moc_qquickvectorimage_p.cpp>
Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash,({ { qMetaTypeId< QCameraPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QMicrophonePermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QBluetoothPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QContactsPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QCalendarPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QLocationPermission >(), Qt::PermissionStatus::Undetermined } }))
static std::vector< std::unique_ptr< QQuickVectorImagePluginGenerator > > createPluginGenerators(const QQuickVectorImageSource &source, QQuickVectorImageGenerator::GeneratorFlags flags)
#define QQuickVectorImageFormatsPluginFactory_iid