4#include <QtCore/qurl.h>
5#include <QtCore/QScopeGuard>
10#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
11#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
12#include <QtCore/private/qfactoryloader_p.h>
13#include <QtCore/qloggingcategory.h>
15#include <private/qquicktranslate_p.h>
16#include <private/qquickanimation_p.h>
20Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, itemGenPluginLoader,
22 QLatin1String(
"/vectorimageformats"), Qt::CaseInsensitive))
24static bool useQmlGenerator()
26 static const bool val = !qEnvironmentVariableIsSet(
"QT_QUICKVECTORIMAGE_USE_ITEM_GENERATOR");
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
59 Q_Q(QQuickVectorImage);
60 if (sourceFile == source)
65 emit q->sourceChanged();
70 Q_Q(QQuickVectorImage);
72 if (!q->isComponentComplete())
75 QQmlContext *ctx = qmlContext(q);
76 QUrl resolvedUrl = ctx->resolvedUrl(sourceFile);
77 QString localFile = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
79 if (localFile.isEmpty())
82 if (rootItem && !retainWhileLoading) {
83 rootItem->deleteLater();
85 emit q->generatedItemChanged();
98 if (pendingRootItem !=
nullptr) {
99 delete pendingRootItem;
100 pendingRootItem =
nullptr;
103 QQuickVectorImageGenerator::GeneratorFlags flags;
104 if (preferredRendererType == QQuickVectorImage::CurveRenderer)
105 flags.setFlag(QQuickVectorImageGenerator::CurveRenderer);
107 flags.setFlag(QQuickVectorImageGenerator::AssumeTrustedSource);
109 flags.setFlag(QQuickVectorImageGenerator::AsyncShapes);
111 flags.setFlag(QQuickVectorImageGenerator::AsynchronousLoading);
113 if (useQmlGenerator()) {
114 QQmlIncubator::IncubationMode mode =
115 asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous;
117 if (!context || context->engine() != qmlContext(q)->engine())
118 context.reset(
new QQmlContext(qmlContext(q)->engine()));
120 incubator =
new QQuickVectorImageIncubator(mode, context.get(), q);
121 QObject::connect(incubator, &QQuickVectorImageIncubator::statusUpdated, q,
122 &QQuickVectorImage::statusChanged);
123 QObject::connect(incubator, &QQuickVectorImageIncubator::statusUpdated, q,
124 &QQuickVectorImage::updateItem);
127 QQuickItemGenerator gen(localFile, flags, qmlContext(q));
129 bool generatedWithPlugin =
false;
130 if (flags.testFlag(QQuickVectorImageGenerator::AssumeTrustedSource)) {
131 QFactoryLoader *loader = itemGenPluginLoader();
132 const qsizetype count = loader->keyMap().size();
133 for (qsizetype i = 0; i < count && !generatedWithPlugin; ++i) {
134 QQuickVectorImagePlugin *plugin =
135 qobject_cast<QQuickVectorImagePlugin *>(loader->instance(i));
136 if (plugin !=
nullptr) {
137 std::unique_ptr<QQuickVectorImagePluginGenerator> pluginGen(
138 plugin->createGenerator(localFile));
139 if (pluginGen !=
nullptr)
140 generatedWithPlugin = pluginGen->generate(localFile, &gen);
145 if (!generatedWithPlugin)
148 if (gen.errorState() == QQuickVectorImageGenerator::NoError) {
149 pendingRootItem = gen.takeRootItem();
151 qCWarning(lcQuickVectorImage) <<
"QQuickItemGenerator: failed to generate" << localFile
152 <<
"(errorState:" << gen.errorState() <<
")";
155 emit q->statusChanged();
159void QQuickVectorImage::updateItem()
161 Q_D(QQuickVectorImage);
163 QQuickItem *item =
nullptr;
164 if (d->incubator !=
nullptr) {
165 if (d->incubator->object() ==
nullptr || !d->incubator->isReady())
167 item = qobject_cast<QQuickItem *>(d->incubator->object());
168 if (item ==
nullptr) {
169 qCWarning(lcQuickVectorImage)
170 <<
"QQuickVectorImage::updateItem: Root item not a QQuickItem:"
171 << d->incubator->errors();
175 item = d->pendingRootItem;
176 d->pendingRootItem =
nullptr;
181 if (d->rootItem !=
nullptr)
182 d->rootItem->deleteLater();
184 d->rootItem =
new QQuickItem(
this);
185 d->rootItem->setParentItem(
this);
186 auto emitter = qScopeGuard([&] { emit generatedItemChanged(); });
188 if (item->width() == 0 || item->height() == 0)
191 d->rootItem->setImplicitWidth(item->width());
192 d->rootItem->setImplicitHeight(item->height());
194 item->setParent(d->rootItem);
195 item->setParentItem(d->rootItem);
197 setImplicitWidth(d->rootItem->width());
198 setImplicitHeight(d->rootItem->height());
200 updateAnimationProperties();
201 updateRootItemScale();
204 static int freezeTime = qEnvironmentVariableIntValue(
"QT_QUICKVECTORIMAGE_FREEZE");
205 if (freezeTime != 0) {
208 animations()->setPaused(
true);
209 const QList<QQuickAbstractAnimation *> anims = d->rootItem->findChildren<QQuickAbstractAnimation *>();
210 for (QQuickAbstractAnimation *anim : anims) {
211 if (anim->group() ==
nullptr)
212 anim->setCurrentTime(freezeTime);
217 d->incubator->disconnect(
this);
218 d->incubator->deleteLater();
219 d->incubator =
nullptr;
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
244 : QQuickItem(*(
new QQuickVectorImagePrivate), parent)
246 setFlag(QQuickItem::ItemHasContents,
true);
248 QObject::connect(
this, &QQuickItem::widthChanged,
this, &QQuickVectorImage::updateRootItemScale);
249 QObject::connect(
this, &QQuickItem::heightChanged,
this, &QQuickVectorImage::updateRootItemScale);
250 QObject::connect(
this, &QQuickVectorImage::fillModeChanged,
this, &QQuickVectorImage::updateRootItemScale);
253QQuickVectorImage::~QQuickVectorImage()
255 Q_D(QQuickVectorImage);
258 d->incubator =
nullptr;
262
263
264
265
266
267
268
269
270QUrl QQuickVectorImage::source()
const
272 Q_D(
const QQuickVectorImage);
273 return d->sourceFile;
276void QQuickVectorImage::setSource(
const QUrl &source)
278 Q_D(QQuickVectorImage);
279 d->setSource(source);
282void QQuickVectorImage::updateRootItemScale()
284 Q_D(QQuickVectorImage);
286 if (d->rootItem ==
nullptr
287 || qFuzzyIsNull(d->rootItem->width())
288 || qFuzzyIsNull(d->rootItem->height())) {
292 auto xformProp = d->rootItem->transform();
293 QQuickScale *scaleTransform =
nullptr;
294 if (xformProp.count(&xformProp) == 0) {
295 scaleTransform =
new QQuickScale;
296 scaleTransform->setParent(d->rootItem);
297 xformProp.append(&xformProp, scaleTransform);
299 scaleTransform = qobject_cast<QQuickScale *>(xformProp.at(&xformProp, 0));
302 if (scaleTransform !=
nullptr) {
303 qreal xScale = width() / d->rootItem->width();
304 qreal yScale = height() / d->rootItem->height();
306 switch (d->fillMode) {
307 case QQuickVectorImage::NoResize:
308 xScale = yScale = 1.0;
310 case QQuickVectorImage::PreserveAspectFit:
311 xScale = yScale = qMin(xScale, yScale);
313 case QQuickVectorImage::PreserveAspectCrop:
314 xScale = yScale = qMax(xScale, yScale);
316 case QQuickVectorImage::Stretch:
321 scaleTransform->setXScale(xScale);
322 scaleTransform->setYScale(yScale);
326void QQuickVectorImage::updateAnimationProperties()
328 Q_D(QQuickVectorImage);
329 if (Q_UNLIKELY(d->rootItem ==
nullptr || d->rootItem->childItems().isEmpty()))
332 QQuickItem *childItem = d->rootItem->childItems().first();
333 if (Q_LIKELY(d->animations !=
nullptr)) {
334 childItem->setProperty(
"loops", d->animations->loops());
335 childItem->setProperty(
"paused", d->animations->paused());
339QQuickVectorImageAnimations *QQuickVectorImage::animations()
341 Q_D(QQuickVectorImage);
342 if (d->animations ==
nullptr) {
343 d->animations =
new QQuickVectorImageAnimations;
344 QQml_setParent_noEvent(d->animations,
this);
345 QObject::connect(d->animations, &QQuickVectorImageAnimations::loopsChanged,
this, &QQuickVectorImage::updateAnimationProperties);
346 QObject::connect(d->animations, &QQuickVectorImageAnimations::pausedChanged,
this, &QQuickVectorImage::updateAnimationProperties);
349 return d->animations;
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
372QQuickVectorImage::FillMode QQuickVectorImage::fillMode()
const
374 Q_D(
const QQuickVectorImage);
378void QQuickVectorImage::setFillMode(FillMode newFillMode)
380 Q_D(QQuickVectorImage);
381 if (d->fillMode == newFillMode)
383 d->fillMode = newFillMode;
384 emit fillModeChanged();
388
389
390
391
392
393
394
395
396
397
398
399
400
402QQuickVectorImage::RendererType QQuickVectorImage::preferredRendererType()
const
404 Q_D(
const QQuickVectorImage);
405 return d->preferredRendererType;
408void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRendererType)
410 Q_D(QQuickVectorImage);
411 if (d->preferredRendererType == newPreferredRendererType)
413 d->preferredRendererType = newPreferredRendererType;
415 emit preferredRendererTypeChanged();
419
420
421
422
423
424
425
426
427
428
429
430
431
432
434bool QQuickVectorImage::asynchronousShapes()
const
436 Q_D(
const QQuickVectorImage);
437 return d->m_asyncShapes;
440void QQuickVectorImage::setAsynchronousShapes(
bool asynchronous)
442 Q_D(QQuickVectorImage);
443 if (d->m_asyncShapes == asynchronous)
445 d->m_asyncShapes = asynchronous;
446 emit asynchronousShapesChanged();
450
451
452
453
454
455
456
457
458
459
460
462bool QQuickVectorImage::asynchronous()
const
464 Q_D(
const QQuickVectorImage);
465 return d->asynchronous;
468void QQuickVectorImage::setAsynchronous(
bool asynchronous)
470 Q_D(QQuickVectorImage);
471 if (d->asynchronous == asynchronous)
473 d->asynchronous = asynchronous;
474 emit asynchronousChanged();
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493bool QQuickVectorImage::retainWhileLoading()
const
495 Q_D(
const QQuickVectorImage);
496 return d->retainWhileLoading;
499void QQuickVectorImage::setRetainWhileLoading(
bool retainWhileLoading)
501 Q_D(QQuickVectorImage);
502 if (d->retainWhileLoading == retainWhileLoading)
504 d->retainWhileLoading = retainWhileLoading;
505 emit retainWhileLoadingChanged();
509
510
511
512
513
514
515
516
517
518
519QQuickVectorImage::Status QQuickVectorImage::status()
const
521 Q_D(
const QQuickVectorImage);
522 if (d->incubator ==
nullptr) {
523 if (d->rootItem ==
nullptr)
526 return Status::Ready;
529 switch (d->incubator->status()) {
530 case QQmlIncubator::Null:
532 case QQmlIncubator::Loading:
533 return Status::Loading;
534 case QQmlIncubator::Error:
535 return Status::Error;
536 case QQmlIncubator::Ready:
537 return Status::Ready;
540 return Status::Error;
544
545
546
547
548
549
550
551
552
553
554
555
556
557
559bool QQuickVectorImage::assumeTrustedSource()
const
561 Q_D(
const QQuickVectorImage);
562 return d->assumeTrustedSource;
565void QQuickVectorImage::setAssumeTrustedSource(
bool assumeTrustedSource)
567 Q_D(QQuickVectorImage);
568 if (d->assumeTrustedSource == assumeTrustedSource)
570 d->assumeTrustedSource = assumeTrustedSource;
572 emit assumeTrustedSourceChanged();
576
577
578
579
580
581
582
584QQuickItem *QQuickVectorImage::generatedItem()
const
586 Q_D(
const QQuickVectorImage);
587 return d->rootItem ? d->rootItem->childItems().value(0) :
nullptr;
590void QQuickVectorImage::componentComplete()
592 Q_D(QQuickVectorImage);
593 QQuickItem::componentComplete();
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615int QQuickVectorImageAnimations::loops()
const
620void QQuickVectorImageAnimations::setLoops(
int loops)
622 if (m_loops == loops)
628bool QQuickVectorImageAnimations::paused()
const
633void QQuickVectorImageAnimations::setPaused(
bool paused)
635 if (m_paused == paused)
638 emit pausedChanged();
641void QQuickVectorImageAnimations::restart()
643 QQuickVectorImage *parentVectorImage = qobject_cast<QQuickVectorImage *>(parent());
644 if (Q_UNLIKELY(parentVectorImage ==
nullptr)) {
645 qCWarning(lcQuickVectorImage) << Q_FUNC_INFO <<
"Parent is not a VectorImage";
649 QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
651 if (Q_UNLIKELY(d->rootItem ==
nullptr || d->rootItem->childItems().isEmpty()))
654 QQuickItem *childItem = d->rootItem->childItems().first();
655 QMetaObject::invokeMethod(childItem,
"restart");
660#include <moc_qquickvectorimage_p.cpp>
void setSource(const QUrl &source)
\qmlmodule QtQuick.VectorImage \title Qt Quick Vector Image QML Types
QQuickVectorImageIncubator * incubator
#define QQuickVectorImageFormatsPluginFactory_iid