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>
18#include <private/qquicktranslate_p.h>
19#include <private/qquickanimation_p.h>
23using namespace Qt::StringLiterals;
27 QLatin1String(
"/vectorimageformats"), Qt::CaseInsensitive))
29bool QQuickVectorImagePrivate::useQmlGenerator()
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;
39 QQuickVectorImageGenerator::GeneratorFlags flags)
41 std::vector<std::unique_ptr<QQuickVectorImagePluginGenerator>> ret;
42 if (!flags.testFlag(QQuickVectorImageGenerator::AssumeTrustedSource))
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));
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
88void QQuickVectorImagePrivate::setSource(
const QUrl &source)
90 Q_Q(QQuickVectorImage);
91 if (imageSource.source() == source)
94 imageSource.setSource(source);
96 emit q->sourceChanged();
99void QQuickVectorImagePrivate::setSourceData(
const QByteArray &data)
101 imageSource.setData(data);
107bool QQuickVectorImagePrivate::cancelAsyncBuilder()
109 Q_Q(QQuickVectorImage);
110 if (asyncBuilder ==
nullptr)
113 asyncBuilder->disconnect(q);
114 asyncBuilder->cancel();
115 asyncBuilder->deleteLater();
116 asyncBuilder =
nullptr;
120void QQuickVectorImagePrivate::loadFile()
122 Q_Q(QQuickVectorImage);
124 if (!q->isComponentComplete())
127 QQmlContext *ctx = qmlContext(q);
128 imageSource.resolveLocalFileName(ctx);
130 const bool asyncBuilderCancelled = cancelAsyncBuilder();
131 const bool startsAsyncBuilder = !useQmlGenerator() && asynchronous && !imageSource.isEmpty();
133 if (rootItem && (!retainWhileLoading || imageSource.isEmpty())) {
134 rootItem->deleteLater();
136 emit q->generatedItemChanged();
138 if (incubator ==
nullptr && !startsAsyncBuilder)
139 emit q->statusChanged();
140 }
else if (asyncBuilderCancelled && imageSource.isEmpty()) {
141 emit q->statusChanged();
144 if (imageSource.isEmpty())
147 if (incubator !=
nullptr) {
150 QObject *obj = incubator->object();
153 incubator->disconnect(q);
154 incubator->deleteLater();
157 if (pendingRootItem !=
nullptr) {
158 delete pendingRootItem;
159 pendingRootItem =
nullptr;
162 QQuickVectorImageGenerator::GeneratorFlags flags;
163 if (preferredRendererType == QQuickVectorImage::CurveRenderer)
164 flags.setFlag(QQuickVectorImageGenerator::CurveRenderer);
165 if (assumeTrustedSource)
166 flags.setFlag(QQuickVectorImageGenerator::AssumeTrustedSource);
168 flags.setFlag(QQuickVectorImageGenerator::AsyncShapes);
170 flags.setFlag(QQuickVectorImageGenerator::AsynchronousLoading);
172 if (useQmlGenerator()) {
173 QQmlIncubator::IncubationMode mode =
174 asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous;
176 if (!context || context->engine() != qmlContext(q)->engine())
177 context.reset(
new QQmlContext(qmlContext(q)->engine()));
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();
190 QQuickItemGenerator gen(imageSource, flags, qmlContext(q));
192 bool generatedWithPlugin =
false;
193 const auto pluginGenerators = createPluginGenerators(imageSource, flags);
194 for (
const auto &pluginGen : pluginGenerators) {
195 if ((generatedWithPlugin = pluginGen->generate(&gen)))
199 if (!generatedWithPlugin)
202 if (gen.errorState() != QQuickVectorImageGenerator::NoError) {
203 qCWarning(lcQuickVectorImage)
204 <<
"QQuickItemGenerator: failed to generate" << imageSource
205 <<
"(errorState:" << gen.errorState() <<
")";
207 pendingRootItem = gen.takeRootItem();
213void QQuickVectorImage::updateItem()
215 Q_D(QQuickVectorImage);
217 const QQuickItem *oldGenItem = generatedItem();
218 auto emitter = qScopeGuard([&] {
219 if (generatedItem() != oldGenItem)
220 emit generatedItemChanged();
221 emit statusChanged();
224 QQuickItem *item =
nullptr;
225 if (d->incubator !=
nullptr) {
226 if (d->incubator->object() ==
nullptr || !d->incubator->isReady())
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();
235 }
else if (d->asyncBuilder !=
nullptr) {
236 if (d->asyncBuilder->state() != QQuickAsyncItemBuilder::State::Finished)
238 item = d->asyncBuilder->takeRootItem();
239 d->asyncBuilder->disconnect(
this);
240 d->asyncBuilder->deleteLater();
241 d->asyncBuilder =
nullptr;
245 item = d->pendingRootItem;
246 d->pendingRootItem =
nullptr;
251 if (d->rootItem !=
nullptr)
252 d->rootItem->deleteLater();
254 d->rootItem =
new QQuickItem(
this);
255 d->rootItem->setParentItem(
this);
256 d->rootItem->setImplicitWidth(item->width());
257 d->rootItem->setImplicitHeight(item->height());
259 item->setParent(d->rootItem);
260 item->setParentItem(d->rootItem);
262 setImplicitWidth(d->rootItem->width());
263 setImplicitHeight(d->rootItem->height());
265 updateAnimationProperties();
266 updateRootItemScale();
269 static int freezeTime = qEnvironmentVariableIntValue(
"QT_QUICKVECTORIMAGE_FREEZE");
270 if (freezeTime != 0) {
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);
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)]() {
289 Q_UNUSED(componentGuard);
293 d->incubator->disconnect(
this);
294 d->incubator->deleteLater();
295 d->incubator =
nullptr;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
320 : QQuickItem(*(
new QQuickVectorImagePrivate), parent)
322 setFlag(QQuickItem::ItemHasContents,
true);
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);
329QQuickVectorImage::~QQuickVectorImage()
331 Q_D(QQuickVectorImage);
334 d->incubator =
nullptr;
337 delete d->asyncBuilder;
338 d->asyncBuilder =
nullptr;
342
343
344
345
346
347
348
349
350QUrl QQuickVectorImage::source()
const
352 Q_D(
const QQuickVectorImage);
353 return d->imageSource.source();
356void QQuickVectorImage::setSource(
const QUrl &source)
358 Q_D(QQuickVectorImage);
359 d->setSource(source);
362void QQuickVectorImage::updateRootItemScale()
364 Q_D(QQuickVectorImage);
366 if (d->rootItem ==
nullptr
367 || qFuzzyIsNull(d->rootItem->width())
368 || qFuzzyIsNull(d->rootItem->height())) {
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);
379 scaleTransform = qobject_cast<QQuickScale *>(xformProp.at(&xformProp, 0));
382 if (scaleTransform !=
nullptr) {
383 qreal xScale = width() / d->rootItem->width();
384 qreal yScale = height() / d->rootItem->height();
386 switch (d->fillMode) {
387 case QQuickVectorImage::NoResize:
388 xScale = yScale = 1.0;
390 case QQuickVectorImage::PreserveAspectFit:
391 xScale = yScale = qMin(xScale, yScale);
393 case QQuickVectorImage::PreserveAspectCrop:
394 xScale = yScale = qMax(xScale, yScale);
396 case QQuickVectorImage::Stretch:
401 scaleTransform->setXScale(xScale);
402 scaleTransform->setYScale(yScale);
406void QQuickVectorImage::updateAnimationProperties()
408 Q_D(QQuickVectorImage);
409 if (Q_UNLIKELY(d->rootItem ==
nullptr || d->rootItem->childItems().isEmpty()))
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());
418 childItem->setProperty(
"loops", d->animations->loops());
419 childItem->setProperty(
"paused", d->animations->paused());
424QQuickVectorImageAnimations *QQuickVectorImage::animations()
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);
434 return d->animations;
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
457QQuickVectorImage::FillMode QQuickVectorImage::fillMode()
const
459 Q_D(
const QQuickVectorImage);
463void QQuickVectorImage::setFillMode(FillMode newFillMode)
465 Q_D(QQuickVectorImage);
466 if (d->fillMode == newFillMode)
468 d->fillMode = newFillMode;
469 emit fillModeChanged();
473
474
475
476
477
478
479
480
481
482
483
484
485
487QQuickVectorImage::RendererType QQuickVectorImage::preferredRendererType()
const
489 Q_D(
const QQuickVectorImage);
490 return d->preferredRendererType;
493void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRendererType)
495 Q_D(QQuickVectorImage);
496 if (d->preferredRendererType == newPreferredRendererType)
498 d->preferredRendererType = newPreferredRendererType;
500 emit preferredRendererTypeChanged();
504
505
506
507
508
509
510
511
512
513
514
515
516
517
519bool QQuickVectorImage::asynchronousShapes()
const
521 Q_D(
const QQuickVectorImage);
522 return d->m_asyncShapes;
525void QQuickVectorImage::setAsynchronousShapes(
bool asynchronous)
527 Q_D(QQuickVectorImage);
528 if (d->m_asyncShapes == asynchronous)
530 d->m_asyncShapes = asynchronous;
531 emit asynchronousShapesChanged();
535
536
537
538
539
540
541
542
543
544
545
547bool QQuickVectorImage::asynchronous()
const
549 Q_D(
const QQuickVectorImage);
550 return d->asynchronous;
553void QQuickVectorImage::setAsynchronous(
bool asynchronous)
555 Q_D(QQuickVectorImage);
556 if (d->asynchronous == asynchronous)
558 d->asynchronous = asynchronous;
559 emit asynchronousChanged();
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578bool QQuickVectorImage::retainWhileLoading()
const
580 Q_D(
const QQuickVectorImage);
581 return d->retainWhileLoading;
584void QQuickVectorImage::setRetainWhileLoading(
bool retainWhileLoading)
586 Q_D(QQuickVectorImage);
587 if (d->retainWhileLoading == retainWhileLoading)
589 d->retainWhileLoading = retainWhileLoading;
590 emit retainWhileLoadingChanged();
594
595
596
597
598
599
600
601
602
603
604QQuickVectorImage::Status QQuickVectorImage::status()
const
606 Q_D(
const QQuickVectorImage);
607 if (d->asyncBuilder !=
nullptr)
608 return Status::Loading;
610 if (d->incubator ==
nullptr) {
611 if (d->rootItem !=
nullptr)
612 return Status::Ready;
613 else if (!isComponentComplete() || d->imageSource.isEmpty())
616 return Status::Error;
619 switch (d->incubator->status()) {
620 case QQmlIncubator::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;
630 return Status::Error;
634
635
636
637
638
639
640
641
642
643
644
645
646
647
649bool QQuickVectorImage::assumeTrustedSource()
const
651 Q_D(
const QQuickVectorImage);
652 return d->assumeTrustedSource;
655void QQuickVectorImage::setAssumeTrustedSource(
bool assumeTrustedSource)
657 Q_D(QQuickVectorImage);
658 if (d->assumeTrustedSource == assumeTrustedSource)
660 d->assumeTrustedSource = assumeTrustedSource;
662 emit assumeTrustedSourceChanged();
666
667
668
669
670
671
672
674QQuickItem *QQuickVectorImage::generatedItem()
const
676 Q_D(
const QQuickVectorImage);
677 return d->rootItem ? d->rootItem->childItems().value(0) :
nullptr;
680void QQuickVectorImage::componentComplete()
682 Q_D(QQuickVectorImage);
683 QQuickItem::componentComplete();
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705int QQuickVectorImageAnimations::loops()
const
710void QQuickVectorImageAnimations::setLoops(
int loops)
712 if (m_loops == loops)
718bool QQuickVectorImageAnimations::paused()
const
723void QQuickVectorImageAnimations::setPaused(
bool paused)
725 if (m_paused == paused)
728 emit pausedChanged();
731void QQuickVectorImageAnimations::restart()
733 QQuickVectorImage *parentVectorImage = qobject_cast<QQuickVectorImage *>(parent());
734 if (Q_UNLIKELY(parentVectorImage ==
nullptr)) {
735 qCWarning(lcQuickVectorImage) << Q_FUNC_INFO <<
"Parent is not a VectorImage";
739 QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
741 if (Q_UNLIKELY(d->rootItem ==
nullptr || d->rootItem->childItems().isEmpty()))
744 QQuickItem *childItem = d->rootItem->childItems().first();
745 QMetaObject::invokeMethod(childItem,
"restart");
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