6#include <QtCore/private/qfactoryloader_p.h>
7#include <QtQml/qqmlcontext.h>
8#include <QtQml/private/qqmlcomponent_p.h>
9#include <QtQml/private/qqmlmetatype_p.h>
13Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, vectorImagePluginLoader,
14 (QQuickVectorImageFormatsPluginFactory_iid,
15 QLatin1String(
"/vectorimageformats"),
18void QQuickVectorImageWorker::process()
20 Q_ASSERT(m_generator !=
nullptr);
23 bool generatedWithPlugin =
false;
24 for (
const auto &pluginGenerator : std::as_const(m_pluginGenerators)) {
25 if ((generatedWithPlugin = pluginGenerator->generate(m_generator.get())))
29 if (!generatedWithPlugin)
30 m_generator->generate();
35QQuickVectorImageIncubator::QQuickVectorImageIncubator(IncubationMode incubationMode,
38 : QObject(*
new QQuickVectorImageIncubatorPrivate, parent)
39 , QQmlIncubator(incubationMode)
41 Q_D(QQuickVectorImageIncubator);
42 d->qmlContext = context;
45QQuickVectorImageIncubator::~QQuickVectorImageIncubator()
47 Q_D(QQuickVectorImageIncubator);
48 if (d->workerThread !=
nullptr && d->workerThread->isRunning()) {
49 d->workerThread->quit();
50 d->workerThread->wait();
54QQmlIncubator::Status QQuickVectorImageIncubator::status()
const
56 Q_D(
const QQuickVectorImageIncubator);
60void QQuickVectorImageIncubator::start(
const QQuickVectorImageSource &source,
61 QQuickVectorImageGenerator::GeneratorFlags flags)
63 Q_D(QQuickVectorImageIncubator);
64 Q_ASSERT(d->generatorWorker ==
nullptr);
65 Q_ASSERT(d->workerThread ==
nullptr);
70 const bool asynchronous = flags.testFlag(QQuickVectorImageGenerator::AsynchronousLoading);
72 d->workerThread.reset(
new QThread);
74 d->generatorWorker.reset(
new QQuickVectorImageWorker);
75 d->generatorWorker->createGenerator(source, flags);
76 connect(d->generatorWorker.get(), &QQuickVectorImageWorker::finished,
77 this, &QQuickVectorImageIncubator::generatorFinished);
79 if (flags.testFlag(QQuickVectorImageGenerator::AssumeTrustedSource)) {
80 QFactoryLoader *loader = vectorImagePluginLoader();
82 const qsizetype count = loader->keyMap().size();
83 for (qsizetype i = 0; i < count; ++i) {
84 QQuickVectorImagePlugin *plugin = qobject_cast<QQuickVectorImagePlugin *>(loader->instance(i));
85 if (plugin !=
nullptr) {
86 QQuickVectorImagePluginGenerator *pluginGenerator = plugin->createGenerator(source);
87 if (pluginGenerator !=
nullptr)
88 d->generatorWorker->addPluginGenerator(pluginGenerator);
93 if (d->workerThread !=
nullptr) {
94 d->generatorWorker->moveToThread(d->workerThread.get());
95 d->workerThread->start();
99 QMetaObject::invokeMethod(d->generatorWorker.get(), &QQuickVectorImageWorker::process, Qt::AutoConnection);
102void QQuickVectorImageIncubator::generatorFinished()
104 Q_D(QQuickVectorImageIncubator);
105 Q_ASSERT(d->componentGuard.component() ==
nullptr);
106 Q_ASSERT(d->generatorWorker !=
nullptr);
107 Q_ASSERT(d->generatorWorker->generator() !=
nullptr);
108 Q_ASSERT(d->workerThread ==
nullptr || d->workerThread->isRunning());
110 const QQuickVectorImageGenerator::ErrorState errorState = d->generatorWorker->generator()->errorState();
111 const bool asynchronous = d->generatorWorker->generator()->generatorFlags().testFlag(QQuickVectorImageGenerator::AsynchronousLoading);
112 const QByteArray result = d->generatorWorker->generator()->result();
114 d->generatorWorker->disconnect(
this);
115 d->generatorWorker.release()->deleteLater();
117 if (d->workerThread !=
nullptr) {
118 d->workerThread->quit();
119 d->workerThread->wait();
120 d->workerThread.reset(
nullptr);
123 if (Q_LIKELY(errorState == QQuickVectorImageGenerator::NoError)) {
124 QQmlEngine *engine = d->qmlContext->engine();
125 if (Q_UNLIKELY(engine ==
nullptr)) {
126 qCWarning(lcQuickVectorImage) <<
"QQuickVectorImageIncubator::generatorFinished: Requires QML engine";
130 d->componentGuard.setComponent(
new QQmlComponent(engine));
131 connect(d->componentGuard.component(), &QQmlComponent::statusChanged,
132 this, &QQuickVectorImageIncubator::componentUpdated);
134 QQmlComponentPrivate *cd = QQmlComponentPrivate::get(d->componentGuard.component());
135 cd->setData(result, QUrl{}, QQmlComponent::Asynchronous);
136 emit d->componentGuard.component()->statusChanged(d->componentGuard.component()->status());
138 d->componentGuard.component()->setData(result, QUrl{});
142 emit statusUpdated();
146QQuickVectorImageIncubatorPrivate::QmlComponentGuard::~QmlComponentGuard()
148 if (m_component !=
nullptr)
149 delete takeComponent();
151 if (m_baseCompilationUnit !=
nullptr) {
152 QQmlMetaType::unregisterInternalCompositeType(m_baseCompilationUnit);
153 m_baseCompilationUnit.reset();
157QQuickVectorImageIncubatorPrivate::QmlComponentGuard QQuickVectorImageIncubatorPrivate::takeComponentGuard()
159 return std::move(componentGuard);
162QQmlComponent *QQuickVectorImageIncubatorPrivate::QmlComponentGuard::takeComponent()
164 QQmlComponent *ret =
nullptr;
165 if (m_component !=
nullptr) {
166 ret = m_component.release();
168 QQmlComponentPrivate *d = QQmlComponentPrivate::get(ret);
169 if (d->compilationUnit() !=
nullptr)
170 m_baseCompilationUnit = d->compilationUnit()->baseCompilationUnit();
176void QQuickVectorImageIncubator::componentUpdated()
178 Q_D(QQuickVectorImageIncubator);
179 Q_ASSERT(d->componentGuard.component() !=
nullptr);
180 Q_ASSERT(d->generatorWorker ==
nullptr);
181 Q_ASSERT(d->workerThread ==
nullptr);
183 if (!d->componentGuard.component()->isLoading()) {
188 QQmlComponent *component = d->componentGuard.takeComponent();
189 if (component->isReady()) {
190 component->create(*
this, d->qmlContext);
192 qCWarning(lcQuickVectorImage) <<
"Component failed to load:"
193 << component->errorString();
195 emit statusUpdated();
198 component->deleteLater();
202void QQuickVectorImageIncubator::statusChanged(Status status)
204 Q_D(QQuickVectorImageIncubator);
205 if (d->status == status)
208 emit statusUpdated();
Combined button and popup list for selecting options.