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