8#include <QtQml/qqmlinfo.h>
10#include <private/qqmlengine_p.h>
11#include <private/qqmlglobal_p.h>
13#include <private/qqmlcomponent_p.h>
14#include <private/qqmlincubator_p.h>
20 m_loader->incubatorStateChanged(status);
25 m_loader->setInitialState(o);
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
50QQuick3DLoader::QQuick3DLoader(QQuick3DNode *parent)
51 : QQuick3DNode(parent)
54 , m_itemContext(
nullptr)
55 , m_incubator(
nullptr)
57 , m_loadingFromSource(
false)
58 , m_asynchronous(
false)
62QQuick3DLoader::~QQuick3DLoader()
66 m_incubator =
nullptr;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
85bool QQuick3DLoader::active()
const
90void QQuick3DLoader::setActive(
bool newVal)
92 if (m_active == newVal)
97 if (m_loadingFromSource) {
100 loadFromSourceComponent();
105 m_incubator->clear();
106 delete m_itemContext;
107 m_itemContext =
nullptr;
112 QQmlContext *context = qmlContext(m_object);
114 QQmlContextData::get(context)->clearContextRecursively();
119 m_item->setParentItem(
nullptr);
120 m_item->setVisible(
false);
124 m_object->deleteLater();
128 emit statusChanged();
130 emit activeChanged();
133void QQuick3DLoader::setSource(QQmlV4FunctionPtr args)
135 bool ipvError =
false;
136 args->setReturnValue(QV4::Encode::undefined());
137 QV4::Scope scope(args->v4engine());
138 QV4::ScopedValue ipv(scope, extractInitialPropertyValues(args, &ipvError));
143 QUrl sourceUrl = resolveSourceUrl(args);
144 if (!ipv->isUndefined()) {
145 disposeInitialPropertyValues();
146 m_initialPropertyValues.set(args->v4engine(), ipv);
148 m_qmlCallingContext.set(scope.engine, scope.engine->qmlContext());
150 setSource(sourceUrl,
false);
154
155
156
157
158
159
160
161
162
164QUrl QQuick3DLoader::source()
const
169void QQuick3DLoader::setSource(
const QUrl &url)
171 setSource(url,
true);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
222QQmlComponent *QQuick3DLoader::sourceComponent()
const
227void QQuick3DLoader::setSourceComponent(QQmlComponent *comp)
229 if (comp == m_component)
234 m_component.setObject(comp,
this);
235 m_loadingFromSource =
false;
238 loadFromSourceComponent();
240 emit sourceComponentChanged();
243void QQuick3DLoader::resetSourceComponent()
245 setSourceComponent(
nullptr);
249
250
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
288QQuick3DLoader::Status QQuick3DLoader::status()
const
294 switch (m_component->status()) {
295 case QQmlComponent::Loading:
297 case QQmlComponent::Error:
299 case QQmlComponent::Null:
307 switch (m_incubator->status()) {
308 case QQmlIncubator::Loading:
310 case QQmlIncubator::Error:
320 return m_source.isEmpty() ? Null : Error;
324
325
326
327
328
329
330
334
335
336
337
338
339
340
341
342
344qreal QQuick3DLoader::progress()
const
351 return m_component->progress();
357
358
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
390bool QQuick3DLoader::asynchronous()
const
392 return m_asynchronous;
395void QQuick3DLoader::setAsynchronous(
bool a)
397 if (m_asynchronous == a)
402 if (!m_asynchronous && isComponentComplete() && m_active) {
403 if (m_loadingFromSource && m_component && m_component->isLoading()) {
405 QUrl currentSource = m_source;
407 m_source = currentSource;
409 }
else if (m_incubator && m_incubator->isLoading()) {
410 m_incubator->forceCompletion();
414 emit asynchronousChanged();
418
419
420
421
422QObject *QQuick3DLoader::item()
const
427void QQuick3DLoader::componentComplete()
429 QQuick3DNode::componentComplete();
431 if (m_loadingFromSource)
437void QQuick3DLoader::sourceLoaded()
439 if (!m_component || !m_component->errors().isEmpty()) {
441 QQmlEnginePrivate::warning(qmlEngine(
this), m_component->errors());
442 if (m_loadingFromSource)
443 emit sourceChanged();
445 emit sourceComponentChanged();
446 emit statusChanged();
447 emit progressChanged();
449 disposeInitialPropertyValues();
453 QQmlContext *creationContext = m_component->creationContext();
454 if (!creationContext)
455 creationContext = qmlContext(
this);
457 QQmlComponentPrivate *cp = QQmlComponentPrivate::get(m_component);
458 QQmlContext *context = [&](){
460 return creationContext;
461 m_itemContext =
new QQmlContext(creationContext);
462 m_itemContext->setContextObject(
this);
463 return m_itemContext;
467 m_incubator =
new QQuick3DLoaderIncubator(
this, m_asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
469 m_component->create(*m_incubator, context);
471 if (m_incubator && m_incubator->status() == QQmlIncubator::Loading)
472 emit statusChanged();
475void QQuick3DLoader::setSource(
const QUrl &sourceUrl,
bool needsClear)
477 if (m_source == sourceUrl)
483 m_source = sourceUrl;
484 m_loadingFromSource =
true;
489 emit sourceChanged();
492void QQuick3DLoader::loadFromSource()
494 if (m_source.isEmpty()) {
495 emit sourceChanged();
496 emit statusChanged();
497 emit progressChanged();
502 if (isComponentComplete()) {
509void QQuick3DLoader::loadFromSourceComponent()
512 emit sourceComponentChanged();
513 emit statusChanged();
514 emit progressChanged();
519 if (isComponentComplete())
523void QQuick3DLoader::clear()
525 disposeInitialPropertyValues();
528 m_incubator->clear();
530 delete m_itemContext;
531 m_itemContext =
nullptr;
535 QQmlContext *context = qmlContext(m_object);
537 QQmlContextData::get(context)->clearContextRecursively();
539 if (m_loadingFromSource && m_component) {
541 QObject::disconnect(m_component, SIGNAL(statusChanged(QQmlComponent::Status)),
542 this, SLOT(sourceLoaded()));
543 QObject::disconnect(m_component, SIGNAL(progressChanged(qreal)),
544 this, SIGNAL(progressChanged()));
545 m_component->deleteLater();
546 m_component.setObject(
nullptr,
this);
547 }
else if (m_component) {
548 m_component.setObject(
nullptr,
this);
555 m_item->setParentItem(
nullptr);
556 m_item->setVisible(
false);
560 m_object->deleteLater();
565void QQuick3DLoader::load()
568 if (!isComponentComplete() || !m_component)
571 if (!m_component->isLoading()) {
574 QObject::connect(m_component, SIGNAL(statusChanged(QQmlComponent::Status)),
575 this, SLOT(sourceLoaded()));
576 QObject::connect(m_component, SIGNAL(progressChanged(qreal)),
577 this, SIGNAL(progressChanged()));
578 emit statusChanged();
579 emit progressChanged();
580 if (m_loadingFromSource)
581 emit sourceChanged();
583 emit sourceComponentChanged();
588void QQuick3DLoader::incubatorStateChanged(QQmlIncubator::Status status)
590 if (status == QQmlIncubator::Loading || status == QQmlIncubator::Null)
593 if (status == QQmlIncubator::Ready) {
594 m_object = m_incubator->object();
595 m_item = qmlobject_cast<QQuick3DNode*>(m_object);
597 m_incubator->clear();
598 }
else if (status == QQmlIncubator::Error) {
599 if (!m_incubator->errors().isEmpty())
600 QQmlEnginePrivate::warning(qmlEngine(
this), m_incubator->errors());
601 delete m_itemContext;
602 m_itemContext =
nullptr;
603 delete m_incubator->object();
607 if (m_loadingFromSource)
608 emit sourceChanged();
610 emit sourceComponentChanged();
611 emit statusChanged();
612 emit progressChanged();
613 if (status == QQmlIncubator::Ready)
615 disposeInitialPropertyValues();
618void QQuick3DLoader::setInitialState(QObject *obj)
620 QQuick3DObject *item = qmlobject_cast<QQuick3DObject*>(obj);
622 item->setParentItem(
this);
626 QQml_setParent_noEvent(m_itemContext, obj);
627 QQml_setParent_noEvent(obj,
this);
628 m_itemContext =
nullptr;
631 if (m_initialPropertyValues.isUndefined())
634 QQmlComponentPrivate *d = QQmlComponentPrivate::get(m_component);
635 Q_ASSERT(d && d->engine());
636 QV4::ExecutionEngine *v4 = d->engine()->handle();
638 QV4::Scope scope(v4);
639 QV4::ScopedValue ipv(scope, m_initialPropertyValues.value());
640 QV4::Scoped<QV4::QmlContext> qmlContext(scope, m_qmlCallingContext.value());
641 d->initializeObjectWithInitialProperties(qmlContext, ipv, obj, QQmlIncubatorPrivate::get(m_incubator)->requiredProperties());
644void QQuick3DLoader::disposeInitialPropertyValues()
649QUrl QQuick3DLoader::resolveSourceUrl(QQmlV4FunctionPtr args)
651 QV4::Scope scope(args->v4engine());
652 QV4::ScopedValue v(scope, (*args)[0]);
653 QString arg = v->toQString();
657 auto context = scope.engine->callingQmlContext();
658 Q_ASSERT(!context.isNull());
659 return context->resolvedUrl(QUrl(arg));
662QV4::ReturnedValue QQuick3DLoader::extractInitialPropertyValues(QQmlV4FunctionPtr args,
bool *error)
664 QV4::Scope scope(args->v4engine());
665 QV4::ScopedValue valuemap(scope, QV4::Encode::undefined());
666 if (args->length() >= 2) {
667 QV4::ScopedValue v(scope, (*args)[1]);
668 if (!v->isObject() || v->as<QV4::ArrayObject>()) {
670 qmlWarning(
this) << QQuick3DLoader::tr(
"setSource: value is not an object");
677 return valuemap->asReturnedValue();
680void QQuick3DLoader::createComponent()
682 const QQmlComponent::CompilationMode mode = m_asynchronous
683 ? QQmlComponent::Asynchronous
684 : QQmlComponent::PreferSynchronous;
685 QQmlContext *context = qmlContext(
this);
686 m_component.setObject(
new QQmlComponent(context->engine(),
687 context->resolvedUrl(m_source),
695#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,...