10#include <QtQml/qqmlinfo.h>
12#include <private/qqmlengine_p.h>
13#include <private/qqmlglobal_p.h>
15#include <private/qqmlcomponent_p.h>
16#include <private/qqmlincubator_p.h>
22 m_loader->incubatorStateChanged(status);
27 m_loader->setInitialState(o);
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
52QQuick3DLoader::QQuick3DLoader(QQuick3DNode *parent)
53 : QQuick3DNode(parent)
56 , m_itemContext(
nullptr)
57 , m_incubator(
nullptr)
59 , m_loadingFromSource(
false)
60 , m_asynchronous(
false)
64QQuick3DLoader::~QQuick3DLoader()
68 m_incubator =
nullptr;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
87bool QQuick3DLoader::active()
const
92void QQuick3DLoader::setActive(
bool newVal)
94 if (m_active == newVal)
99 if (m_loadingFromSource) {
102 loadFromSourceComponent();
107 m_incubator->clear();
108 delete m_itemContext;
109 m_itemContext =
nullptr;
114 QQmlContext *context = qmlContext(m_object);
116 QQmlContextData::get(context)->clearContextRecursively();
121 m_item->setParentItem(
nullptr);
122 m_item->setVisible(
false);
126 m_object->deleteLater();
130 emit statusChanged();
132 emit activeChanged();
135void QQuick3DLoader::setSource(QQmlV4FunctionPtr args)
137 bool ipvError =
false;
138 args->setReturnValue(QV4::Encode::undefined());
139 QV4::Scope scope(args->v4engine());
140 QV4::ScopedValue ipv(scope, extractInitialPropertyValues(args, &ipvError));
145 QUrl sourceUrl = resolveSourceUrl(args);
146 if (!ipv->isUndefined()) {
147 disposeInitialPropertyValues();
148 m_initialPropertyValues.set(args->v4engine(), ipv);
150 m_qmlCallingContext.set(scope.engine, scope.engine->qmlContext());
152 setSource(sourceUrl,
false);
156
157
158
159
160
161
162
163
164
166QUrl QQuick3DLoader::source()
const
171void QQuick3DLoader::setSource(
const QUrl &url)
173 setSource(url,
true);
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
224QQmlComponent *QQuick3DLoader::sourceComponent()
const
229void QQuick3DLoader::setSourceComponent(QQmlComponent *comp)
231 if (comp == m_component)
236 m_component.setObject(comp,
this);
237 m_loadingFromSource =
false;
240 loadFromSourceComponent();
242 emit sourceComponentChanged();
245void QQuick3DLoader::resetSourceComponent()
247 setSourceComponent(
nullptr);
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
290QQuick3DLoader::Status QQuick3DLoader::status()
const
296 switch (m_component->status()) {
297 case QQmlComponent::Loading:
299 case QQmlComponent::Error:
301 case QQmlComponent::Null:
309 switch (m_incubator->status()) {
310 case QQmlIncubator::Loading:
312 case QQmlIncubator::Error:
322 return m_source.isEmpty() ? Null : Error;
326
327
328
329
330
331
332
336
337
338
339
340
341
342
343
344
346qreal QQuick3DLoader::progress()
const
353 return m_component->progress();
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
392bool QQuick3DLoader::asynchronous()
const
394 return m_asynchronous;
397void QQuick3DLoader::setAsynchronous(
bool a)
399 if (m_asynchronous == a)
404 if (!m_asynchronous && isComponentComplete() && m_active) {
405 if (m_loadingFromSource && m_component && m_component->isLoading()) {
407 QUrl currentSource = m_source;
409 m_source = currentSource;
411 }
else if (m_incubator && m_incubator->isLoading()) {
412 m_incubator->forceCompletion();
416 emit asynchronousChanged();
420
421
422
423
424QObject *QQuick3DLoader::item()
const
429void QQuick3DLoader::componentComplete()
431 QQuick3DNode::componentComplete();
433 if (m_loadingFromSource)
439void QQuick3DLoader::sourceLoaded()
441 if (!m_component || !m_component->errors().isEmpty()) {
443 QQmlEnginePrivate::warning(qmlEngine(
this), m_component->errors());
444 if (m_loadingFromSource)
445 emit sourceChanged();
447 emit sourceComponentChanged();
448 emit statusChanged();
449 emit progressChanged();
451 disposeInitialPropertyValues();
455 QQmlContext *creationContext = m_component->creationContext();
456 if (!creationContext)
457 creationContext = qmlContext(
this);
459 QQmlComponentPrivate *cp = QQmlComponentPrivate::get(m_component);
460 QQmlContext *context = [&](){
462 return creationContext;
463 m_itemContext =
new QQmlContext(creationContext);
464 m_itemContext->setContextObject(
this);
465 return m_itemContext;
469 m_incubator =
new QQuick3DLoaderIncubator(
this, m_asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
471 m_component->create(*m_incubator, context);
473 if (m_incubator && m_incubator->status() == QQmlIncubator::Loading)
474 emit statusChanged();
477void QQuick3DLoader::setSource(
const QUrl &sourceUrl,
bool needsClear)
479 if (m_source == sourceUrl)
485 m_source = sourceUrl;
486 m_loadingFromSource =
true;
491 emit sourceChanged();
494void QQuick3DLoader::loadFromSource()
496 if (m_source.isEmpty()) {
497 emit sourceChanged();
498 emit statusChanged();
499 emit progressChanged();
504 if (isComponentComplete()) {
511void QQuick3DLoader::loadFromSourceComponent()
514 emit sourceComponentChanged();
515 emit statusChanged();
516 emit progressChanged();
521 if (isComponentComplete())
525void QQuick3DLoader::clear()
527 disposeInitialPropertyValues();
530 m_incubator->clear();
532 delete m_itemContext;
533 m_itemContext =
nullptr;
537 QQmlContext *context = qmlContext(m_object);
539 QQmlContextData::get(context)->clearContextRecursively();
541 if (m_loadingFromSource && m_component) {
543 QObject::disconnect(m_component, SIGNAL(statusChanged(QQmlComponent::Status)),
544 this, SLOT(sourceLoaded()));
545 QObject::disconnect(m_component, SIGNAL(progressChanged(qreal)),
546 this, SIGNAL(progressChanged()));
547 m_component->deleteLater();
548 m_component.setObject(
nullptr,
this);
549 }
else if (m_component) {
550 m_component.setObject(
nullptr,
this);
557 m_item->setParentItem(
nullptr);
558 m_item->setVisible(
false);
562 m_object->deleteLater();
567void QQuick3DLoader::load()
570 if (!isComponentComplete() || !m_component)
573 if (!m_component->isLoading()) {
576 QObject::connect(m_component, SIGNAL(statusChanged(QQmlComponent::Status)),
577 this, SLOT(sourceLoaded()));
578 QObject::connect(m_component, SIGNAL(progressChanged(qreal)),
579 this, SIGNAL(progressChanged()));
580 emit statusChanged();
581 emit progressChanged();
582 if (m_loadingFromSource)
583 emit sourceChanged();
585 emit sourceComponentChanged();
590void QQuick3DLoader::incubatorStateChanged(QQmlIncubator::Status status)
592 if (status == QQmlIncubator::Loading || status == QQmlIncubator::Null)
595 if (status == QQmlIncubator::Ready) {
596 m_object = m_incubator->object();
597 m_item = qmlobject_cast<QQuick3DNode*>(m_object);
599 m_incubator->clear();
600 }
else if (status == QQmlIncubator::Error) {
601 if (!m_incubator->errors().isEmpty())
602 QQmlEnginePrivate::warning(qmlEngine(
this), m_incubator->errors());
603 delete m_itemContext;
604 m_itemContext =
nullptr;
605 delete m_incubator->object();
609 if (m_loadingFromSource)
610 emit sourceChanged();
612 emit sourceComponentChanged();
613 emit statusChanged();
614 emit progressChanged();
615 if (status == QQmlIncubator::Ready)
617 disposeInitialPropertyValues();
620void QQuick3DLoader::setInitialState(QObject *obj)
622 QQuick3DObject *item = qmlobject_cast<QQuick3DObject*>(obj);
624 item->setParentItem(
this);
628 QQml_setParent_noEvent(m_itemContext, obj);
629 QQml_setParent_noEvent(obj,
this);
630 m_itemContext =
nullptr;
633 if (m_initialPropertyValues.isUndefined())
636 QQmlComponentPrivate *d = QQmlComponentPrivate::get(m_component);
637 Q_ASSERT(d && d->engine());
638 QV4::ExecutionEngine *v4 = d->engine()->handle();
640 QV4::Scope scope(v4);
641 QV4::ScopedValue ipv(scope, m_initialPropertyValues.value());
642 QV4::Scoped<QV4::QmlContext> qmlContext(scope, m_qmlCallingContext.value());
643 d->initializeObjectWithInitialProperties(qmlContext, ipv, obj, QQmlIncubatorPrivate::get(m_incubator)->requiredProperties());
646void QQuick3DLoader::disposeInitialPropertyValues()
651QUrl QQuick3DLoader::resolveSourceUrl(QQmlV4FunctionPtr args)
653 QV4::Scope scope(args->v4engine());
654 QV4::ScopedValue v(scope, (*args)[0]);
655 QString arg = v->toQString();
659 auto context = scope.engine->callingQmlContext();
660 Q_ASSERT(!context.isNull());
661 return context->resolvedUrl(QUrl(arg));
664QV4::ReturnedValue QQuick3DLoader::extractInitialPropertyValues(QQmlV4FunctionPtr args,
bool *error)
666 QV4::Scope scope(args->v4engine());
667 QV4::ScopedValue valuemap(scope, QV4::Encode::undefined());
668 if (args->length() >= 2) {
669 QV4::ScopedValue v(scope, (*args)[1]);
670 if (!v->isObject() || v->as<QV4::ArrayObject>()) {
672 qmlWarning(
this) << QQuick3DLoader::tr(
"setSource: value is not an object");
679 return valuemap->asReturnedValue();
682void QQuick3DLoader::createComponent()
684 const QQmlComponent::CompilationMode mode = m_asynchronous
685 ? QQmlComponent::Asynchronous
686 : QQmlComponent::PreferSynchronous;
687 QQmlContext *context = qmlContext(
this);
688 m_component.setObject(
new QQmlComponent(context->engine(),
689 context->resolvedUrl(m_source),
697#include "moc_qquick3dloader_p.cpp"
void statusChanged(Status) override
Called when the status of the incubator changes.
void setInitialState(QObject *) override
Called after the object is first created, but before complex property bindings are evaluated and,...
Combined button and popup list for selecting options.