1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmltype_p_p.h"
5
6#include <QtQml/qjsvalue.h>
7#include <QtQml/qqmlengine.h>
8#include <QtQml/qqmlcontext.h>
9#include <QtQml/qqmlcomponent.h>
10
11#include <private/qqmlcustomparser_p.h>
12#include <private/qqmldata_p.h>
13#include <private/qqmlmetatypedata_p.h>
14#include <private/qqmlpropertycache_p.h>
15#include <private/qqmltypedata_p.h>
16
17QT_BEGIN_NAMESPACE
18
19QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
20 : regType(type), iid(nullptr), revision(QTypeRevision::zero()),
21 containsRevisionedAttributes(false), baseMetaObject(nullptr),
22 index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
23 haveSuperType(false)
24{
25 switch (type) {
26 case QQmlType::CppType:
27 extraData.cd = new QQmlCppTypeData;
28 extraData.cd->allocationSize = 0;
29 extraData.cd->newFunc = nullptr;
30 extraData.cd->createValueTypeFunc = nullptr;
31 extraData.cd->parserStatusCast = -1;
32 extraData.cd->extFunc = nullptr;
33 extraData.cd->extMetaObject = nullptr;
34 extraData.cd->customParser = nullptr;
35 extraData.cd->attachedPropertiesFunc = nullptr;
36 extraData.cd->attachedPropertiesType = nullptr;
37 extraData.cd->propertyValueSourceCast = -1;
38 extraData.cd->propertyValueInterceptorCast = -1;
39 extraData.cd->finalizerCast = -1;
40 extraData.cd->registerEnumClassesUnscoped = true;
41 extraData.cd->registerEnumsFromRelatedTypes = true;
42 break;
43 case QQmlType::SingletonType:
44 case QQmlType::CompositeSingletonType:
45 extraData.sd = new QQmlSingletonTypeData;
46 extraData.sd->singletonInstanceInfo = nullptr;
47 extraData.sd->extFunc = nullptr;
48 extraData.sd->extMetaObject = nullptr;
49 break;
50 case QQmlType::InterfaceType:
51 extraData.cd = nullptr;
52 break;
53 case QQmlType::CompositeType:
54 extraData.fd = new QQmlCompositeTypeData;
55 break;
56 case QQmlType::InlineComponentType:
57 extraData.id = new QQmlInlineTypeData;
58 break;
59 case QQmlType::SequentialContainerType:
60 extraData.ld = new QQmlSequenceTypeData;
61 break;
62 default: qFatal(msg: "QQmlTypePrivate Internal Error.");
63 }
64}
65
66QQmlTypePrivate::~QQmlTypePrivate()
67{
68 qDeleteAll(c: scopedEnums);
69 for (const auto &metaObject : metaObjects)
70 free(ptr: metaObject.metaObject);
71 switch (regType) {
72 case QQmlType::CppType:
73 delete extraData.cd->customParser;
74 delete extraData.cd;
75 break;
76 case QQmlType::SingletonType:
77 case QQmlType::CompositeSingletonType:
78 delete extraData.sd->singletonInstanceInfo;
79 delete extraData.sd;
80 break;
81 case QQmlType::CompositeType:
82 delete extraData.fd;
83 break;
84 case QQmlType::InlineComponentType:
85 delete extraData.id;
86 break;
87 case QQmlType::SequentialContainerType:
88 delete extraData.ld;
89 break;
90 default: //Also InterfaceType, because it has no extra data
91 break;
92 }
93}
94
95QQmlType::QQmlType() = default;
96QQmlType::QQmlType(const QQmlType &) = default;
97QQmlType::QQmlType(QQmlType &&) = default;
98QQmlType &QQmlType::operator =(const QQmlType &other) = default;
99QQmlType &QQmlType::operator =(QQmlType &&other) = default;
100QQmlType::QQmlType(const QQmlTypePrivate *priv) : d(priv) {}
101QQmlType::~QQmlType() = default;
102
103QHashedString QQmlType::module() const
104{
105 if (!d)
106 return QHashedString();
107 return d->module;
108}
109
110QTypeRevision QQmlType::version() const
111{
112 if (!d)
113 return QTypeRevision();
114 return d->version;
115}
116
117bool QQmlType::availableInVersion(QTypeRevision version) const
118{
119 if (!d)
120 return false;
121
122 if (!version.hasMajorVersion())
123 return true;
124
125 if (version.majorVersion() != d->version.majorVersion())
126 return false;
127
128 return !version.hasMinorVersion() || version.minorVersion() >= d->version.minorVersion();
129}
130
131bool QQmlType::availableInVersion(const QHashedStringRef &module, QTypeRevision version) const
132{
133 if (!d || module != d->module)
134 return false;
135
136 return availableInVersion(version);
137}
138
139QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
140{
141 Q_ASSERT(isComposite());
142 if (!engine)
143 return QQmlType();
144 QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(unNormalizedUrl: sourceUrl()));
145 if (td.isNull() || !td->isComplete())
146 return QQmlType();
147 QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
148 const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
149 return QQmlMetaType::qmlType(mo);
150}
151
152QQmlPropertyCache::ConstPtr QQmlTypePrivate::compositePropertyCache(
153 QQmlEnginePrivate *engine) const
154{
155 // similar logic to resolveCompositeBaseType
156 Q_ASSERT(isComposite());
157 if (!engine)
158 return nullptr;
159 QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(unNormalizedUrl: sourceUrl()));
160 if (td.isNull() || !td->isComplete())
161 return nullptr;
162 QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
163 return compilationUnit->rootPropertyCache();
164}
165
166static bool isPropertyRevisioned(const QMetaObject *mo, int index)
167{
168 return mo->property(index).revision();
169}
170
171void QQmlTypePrivate::init() const
172{
173 if (isSetup.loadAcquire())
174 return;
175
176 QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
177 if (isSetup.loadAcquire())
178 return;
179
180 const QMetaObject *mo = baseMetaObject;
181 if (!mo) {
182 // version 0 singleton type without metaobject information
183 return;
184 }
185
186 auto setupExtendedMetaObject = [&](const QMetaObject *extMetaObject,
187 QObject *(*extFunc)(QObject *)) {
188 if (!extMetaObject)
189 return;
190
191 // XXX - very inefficient
192 QMetaObjectBuilder builder;
193 QQmlMetaType::clone(builder, mo: extMetaObject, ignoreStart: extMetaObject, ignoreEnd: extMetaObject,
194 policy: extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly);
195 QMetaObject *mmo = builder.toMetaObject();
196 mmo->d.superdata = mo;
197 QQmlProxyMetaObject::ProxyData data = { .metaObject: mmo, .createFunc: extFunc, .propertyOffset: 0, .methodOffset: 0 };
198 metaObjects << data;
199 QQmlMetaType::registerMetaObjectForType(metaobject: mmo, type: const_cast<QQmlTypePrivate *>(this));
200 };
201
202 if (regType == QQmlType::SingletonType)
203 setupExtendedMetaObject(extraData.sd->extMetaObject, extraData.sd->extFunc);
204 else if (regType == QQmlType::CppType)
205 setupExtendedMetaObject(extraData.cd->extMetaObject, extraData.cd->extFunc);
206
207 metaObjects.append(other: QQmlMetaType::proxyData(
208 mo, baseMetaObject, lastMetaObject: metaObjects.isEmpty() ? nullptr
209 : metaObjects.constLast().metaObject));
210
211 for (int ii = 0; ii < metaObjects.size(); ++ii) {
212 metaObjects[ii].propertyOffset =
213 metaObjects.at(i: ii).metaObject->propertyOffset();
214 metaObjects[ii].methodOffset =
215 metaObjects.at(i: ii).metaObject->methodOffset();
216 }
217
218 // Check for revisioned details
219 {
220 const QMetaObject *mo = nullptr;
221 if (metaObjects.isEmpty())
222 mo = baseMetaObject;
223 else
224 mo = metaObjects.constFirst().metaObject;
225
226 for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
227 if (isPropertyRevisioned(mo, index: ii))
228 containsRevisionedAttributes = true;
229 }
230
231 for (int ii = 0; !containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
232 if (mo->method(index: ii).revision() != 0)
233 containsRevisionedAttributes = true;
234 }
235 }
236
237 isSetup.storeRelease(newValue: true);
238 lock.unlock();
239}
240
241void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
242{
243 QQmlPropertyCache::ConstPtr cache = (!isEnumFromCacheSetup.loadAcquire() && isComposite())
244 ? compositePropertyCache(engine)
245 : QQmlPropertyCache::ConstPtr();
246
247 // beware: It could be a singleton type without metaobject
248 const QMetaObject *metaObject = !isEnumFromBaseSetup.loadAcquire()
249 ? baseMetaObject
250 : nullptr;
251
252 if (!cache && !metaObject)
253 return;
254
255 init(); // init() can add to the metaObjects list. Therefore, check metaObjects only below
256
257 QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
258
259 if (cache) {
260 insertEnumsFromPropertyCache(cache);
261 isEnumFromCacheSetup.storeRelease(newValue: true);
262 }
263
264 if (metaObject) {
265 insertEnums(metaObject: metaObjects.isEmpty() ? baseMetaObject : metaObjects.constFirst().metaObject);
266 isEnumFromBaseSetup.storeRelease(newValue: true);
267 }
268}
269
270void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
271{
272 // Add any enum values defined by 'related' classes
273 if (regType != QQmlType::CppType || extraData.cd->registerEnumsFromRelatedTypes) {
274 if (const auto *related = metaObject->d.relatedMetaObjects) {
275 while (const QMetaObject *relatedMetaObject = *related) {
276 insertEnums(metaObject: relatedMetaObject);
277 ++related;
278 }
279 }
280 }
281
282 QSet<QString> localEnums;
283 const QMetaObject *localMetaObject = nullptr;
284
285 // Add any enum values defined by this class, overwriting any inherited values
286 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
287 QMetaEnum e = metaObject->enumerator(index: ii);
288 const bool isScoped = e.isScoped();
289 QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : nullptr;
290
291 // We allow enums in sub-classes to overwrite enums from base-classes, such as
292 // ListView.Center (from enum PositionMode) overwriting Item.Center (from enum TransformOrigin).
293 // This is acceptable because the _use_ of the enum from the QML side requires qualification
294 // anyway, i.e. ListView.Center vs. Item.Center.
295 // However if a class defines two enums with the same value, then that must produce a warning
296 // because it represents a valid conflict.
297 if (e.enclosingMetaObject() != localMetaObject) {
298 localEnums.clear();
299 localMetaObject = e.enclosingMetaObject();
300 }
301
302 for (int jj = 0; jj < e.keyCount(); ++jj) {
303 const QString key = QString::fromUtf8(utf8: e.key(index: jj));
304 const int value = e.value(index: jj);
305 if (!isScoped || (regType == QQmlType::CppType && extraData.cd->registerEnumClassesUnscoped)) {
306 if (localEnums.contains(value: key)) {
307 auto existingEntry = enums.find(key);
308 if (existingEntry != enums.end() && existingEntry.value() != value) {
309 qWarning(msg: "Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
310 createEnumConflictReport(metaObject, conflictingKey: key);
311 }
312 } else {
313 localEnums.insert(value: key);
314 }
315 enums.insert(key, value);
316 }
317 if (isScoped)
318 scoped->insert(key, value);
319 }
320
321 if (isScoped) {
322 scopedEnums << scoped;
323 scopedEnumIndex.insert(key: QString::fromUtf8(utf8: e.name()), value: scopedEnums.size()-1);
324 }
325 }
326}
327
328void QQmlTypePrivate::createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const
329{
330 path.append(t: QString::fromUtf8(utf8: metaObject->className()));
331
332 if (metaObject->d.relatedMetaObjects) {
333 const auto *related = metaObject->d.relatedMetaObjects;
334 if (related) {
335 while (*related)
336 createListOfPossibleConflictingItems(metaObject: *related++, enumInfoList, path);
337 }
338 }
339
340 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
341 const auto e = metaObject->enumerator(index: ii);
342
343 for (int jj = 0; jj < e.keyCount(); ++jj) {
344 const QString key = QString::fromUtf8(utf8: e.key(index: jj));
345
346 EnumInfo enumInfo;
347 enumInfo.metaObjectName = QString::fromUtf8(utf8: metaObject->className());
348 enumInfo.enumName = QString::fromUtf8(utf8: e.name());
349 enumInfo.enumKey = key;
350 enumInfo.scoped = e.isScoped();
351 enumInfo.path = path;
352 enumInfo.metaEnumScope = QString::fromUtf8(utf8: e.scope());
353 enumInfoList.append(t: enumInfo);
354 }
355 }
356}
357
358void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const
359{
360 QList<EnumInfo> enumInfoList;
361
362 if (baseMetaObject) // prefer baseMetaObject if available
363 metaObject = baseMetaObject;
364
365 if (!metaObject) { // If there is no metaObject at all return early
366 qWarning() << "No meta object information available. Skipping conflict analysis.";
367 return;
368 }
369
370 createListOfPossibleConflictingItems(metaObject, enumInfoList, path: QStringList());
371
372 qWarning().noquote() << QLatin1String("Possible conflicting items:");
373 // find items with conflicting key
374 for (const auto &i : std::as_const(t&: enumInfoList)) {
375 if (i.enumKey == conflictingKey)
376 qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
377 << i.metaEnumScope << " injected by " << i.path.join(sep: QLatin1String("->"));
378 }
379}
380
381void QQmlTypePrivate::insertEnumsFromPropertyCache(
382 const QQmlPropertyCache::ConstPtr &cache) const
383{
384 const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
385
386 for (const QQmlPropertyCache *currentCache = cache.data();
387 currentCache && currentCache->metaObject() != cppMetaObject;
388 currentCache = currentCache->parent().data()) {
389
390 int count = currentCache->qmlEnumCount();
391 for (int ii = 0; ii < count; ++ii) {
392 QStringHash<int> *scoped = new QStringHash<int>();
393 QQmlEnumData *enumData = currentCache->qmlEnum(index: ii);
394
395 for (int jj = 0; jj < enumData->values.size(); ++jj) {
396 const QQmlEnumValue &value = enumData->values.at(i: jj);
397 enums.insert(key: value.namedValue, value: value.value);
398 scoped->insert(key: value.namedValue, value: value.value);
399 }
400 scopedEnums << scoped;
401 scopedEnumIndex.insert(key: enumData->name, value: scopedEnums.size()-1);
402 }
403 }
404 insertEnums(metaObject: cppMetaObject);
405}
406
407void QQmlTypePrivate::setContainingType(QQmlType *containingType)
408{
409 Q_ASSERT(regType == QQmlType::InlineComponentType);
410 extraData.id->containingType = containingType->d.data();
411}
412
413void QQmlTypePrivate::setName(const QString &uri, const QString &element)
414{
415 module = uri;
416 elementName = element;
417 name = uri.isEmpty() ? element : (uri + QLatin1Char('/') + element);
418}
419
420QByteArray QQmlType::typeName() const
421{
422 if (d) {
423 if (d->regType == SingletonType || d->regType == CompositeSingletonType)
424 return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
425 else if (d->baseMetaObject)
426 return d->baseMetaObject->className();
427 }
428 return QByteArray();
429}
430
431QString QQmlType::elementName() const
432{
433 if (!d)
434 return QString();
435 return d->elementName;
436}
437
438QString QQmlType::qmlTypeName() const
439{
440 if (!d)
441 return QString();
442 return d->name;
443}
444
445/*!
446 \internal
447 Allocates and initializes an object if the type is creatable.
448 Returns a pointer to the object, or nullptr if the type was
449 not creatable.
450 */
451QObject *QQmlType::create() const
452{
453 void *unused;
454 return create(&unused, 0);
455}
456
457/*!
458 \internal
459 \brief Like create without arguments, but allocates some extra space after the object.
460 \param memory An out-only argument. *memory will point to the start of the additionally
461 allocated memory.
462 \param additionalMemory The amount of extra memory in bytes that shoudld be allocated.
463
464 \note This function is used to allocate the QQmlData next to the object in the
465 QQmlObjectCreator.
466
467 \overload
468 */
469QObject *QQmlType::create(void **memory, size_t additionalMemory) const
470{
471 if (!d || !isCreatable())
472 return nullptr;
473
474 d->init();
475
476 QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize + additionalMemory);
477 d->extraData.cd->newFunc(rv, d->extraData.cd->userdata);
478
479 createProxy(instance: rv);
480 *memory = ((char *)rv) + d->extraData.cd->allocationSize;
481 return rv;
482}
483
484/*!
485 \internal
486 Like create, but also allocates memory behind the object, constructs a QQmlData there
487 and lets the objects declarativeData point to the newly created QQmlData.
488 */
489QObject *QQmlType::createWithQQmlData() const
490{
491 void *ddataMemory = nullptr;
492 auto instance = create(memory: &ddataMemory, additionalMemory: sizeof(QQmlData));
493 if (!instance)
494 return nullptr;
495 QObjectPrivate* p = QObjectPrivate::get(o: instance);
496 Q_ASSERT(!p->isDeletingChildren);
497 if (!p->declarativeData)
498 p->declarativeData = new (ddataMemory) QQmlData(QQmlData::DoesNotOwnMemory);
499 return instance;
500}
501
502QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
503{
504 if (!d)
505 return nullptr;
506 if (d->regType != SingletonType && d->regType != CompositeSingletonType)
507 return nullptr;
508 return d->extraData.sd->singletonInstanceInfo;
509}
510
511QQmlCustomParser *QQmlType::customParser() const
512{
513 if (!d)
514 return nullptr;
515 if (d->regType != CppType)
516 return nullptr;
517 return d->extraData.cd->customParser;
518}
519
520QQmlType::CreateValueTypeFunc QQmlType::createValueTypeFunction() const
521{
522 if (!d || d->regType != CppType)
523 return nullptr;
524 return d->extraData.cd->createValueTypeFunc;
525}
526
527bool QQmlType::canConstructValueType() const
528{
529 if (!d || d->regType != CppType)
530 return false;
531 return d->extraData.cd->constructValueType;
532}
533
534bool QQmlType::canPopulateValueType() const
535{
536 if (!d || d->regType != CppType)
537 return false;
538 return d->extraData.cd->populateValueType;
539}
540
541QQmlType::CreateFunc QQmlType::createFunction() const
542{
543 if (!d || d->regType != CppType)
544 return nullptr;
545 return d->extraData.cd->newFunc;
546}
547
548QString QQmlType::noCreationReason() const
549{
550 if (!d || d->regType != CppType)
551 return QString();
552 return d->extraData.cd->noCreationReason;
553}
554
555bool QQmlType::isCreatable() const
556{
557 return d && d->regType == CppType && d->extraData.cd->newFunc;
558}
559
560QQmlType::ExtensionFunc QQmlType::extensionFunction() const
561{
562 if (!d)
563 return nullptr;
564
565 switch (d->regType) {
566 case CppType:
567 return d->extraData.cd->extFunc;
568 case SingletonType:
569 return d->extraData.sd->extFunc;
570 default:
571 return nullptr;
572 }
573}
574
575const QMetaObject *QQmlType::extensionMetaObject() const
576{
577 if (!d)
578 return nullptr;
579
580 switch (d->regType) {
581 case CppType:
582 return d->extraData.cd->extMetaObject;
583 case SingletonType:
584 return d->extraData.sd->extMetaObject;
585 default:
586 return nullptr;
587 }
588}
589
590bool QQmlType::isExtendedType() const
591{
592 if (!d)
593 return false;
594 d->init();
595
596 return !d->metaObjects.isEmpty();
597}
598
599bool QQmlType::isSingleton() const
600{
601 return d && (d->regType == SingletonType || d->regType == CompositeSingletonType);
602}
603
604bool QQmlType::isInterface() const
605{
606 return d && d->regType == InterfaceType;
607}
608
609bool QQmlType::isComposite() const
610{
611 return d && d->isComposite();
612}
613
614bool QQmlType::isCompositeSingleton() const
615{
616 // if the outer type is a composite singleton, d->regType will indicate that even for
617 // the inline component type
618 // however, inline components can -at least for now- never be singletons
619 // so we just do one additional check
620 return d && d->regType == CompositeSingletonType && !isInlineComponentType();
621}
622
623bool QQmlType::isQObjectSingleton() const
624{
625 return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->qobjectCallback;
626}
627
628bool QQmlType::isQJSValueSingleton() const
629{
630 return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback;
631}
632
633bool QQmlType::isSequentialContainer() const
634{
635 return d && d->regType == SequentialContainerType;
636}
637
638QMetaType QQmlType::typeId() const
639{
640 return d ? d->typeId : QMetaType{};
641}
642
643QMetaType QQmlType::qListTypeId() const
644{
645 return d ? d->listId : QMetaType{};
646}
647
648QMetaSequence QQmlType::listMetaSequence() const
649{
650 return isSequentialContainer() ? *d->extraData.ld : QMetaSequence();
651}
652
653const QMetaObject *QQmlType::metaObject() const
654{
655 if (!d)
656 return nullptr;
657 d->init();
658
659 if (d->metaObjects.isEmpty())
660 return d->baseMetaObject;
661 else
662 return d->metaObjects.constFirst().metaObject;
663
664}
665
666const QMetaObject *QQmlType::baseMetaObject() const
667{
668 return d ? d->baseMetaObject : nullptr;
669}
670
671bool QQmlType::containsRevisionedAttributes() const
672{
673 if (!d)
674 return false;
675 d->init();
676
677 return d->containsRevisionedAttributes;
678}
679
680QTypeRevision QQmlType::metaObjectRevision() const
681{
682 return d ? d->revision : QTypeRevision();
683}
684
685QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
686{
687 if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
688 return base->extraData.cd->attachedPropertiesFunc;
689 return nullptr;
690}
691
692const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
693{
694 if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
695 return base->extraData.cd->attachedPropertiesType;
696 return nullptr;
697}
698
699int QQmlType::parserStatusCast() const
700{
701 if (!d || d->regType != CppType)
702 return -1;
703 return d->extraData.cd->parserStatusCast;
704}
705
706int QQmlType::propertyValueSourceCast() const
707{
708 if (!d || d->regType != CppType)
709 return -1;
710 return d->extraData.cd->propertyValueSourceCast;
711}
712
713int QQmlType::propertyValueInterceptorCast() const
714{
715 if (!d || d->regType != CppType)
716 return -1;
717 return d->extraData.cd->propertyValueInterceptorCast;
718}
719
720int QQmlType::finalizerCast() const
721{
722 if (!d || d->regType != CppType)
723 return -1;
724 return d->extraData.cd->finalizerCast;
725}
726
727const char *QQmlType::interfaceIId() const
728{
729 if (!d || d->regType != InterfaceType)
730 return nullptr;
731 return d->iid;
732}
733
734int QQmlType::index() const
735{
736 return d ? d->index : -1;
737}
738
739bool QQmlType::isInlineComponentType() const {
740 return d ? d->regType == QQmlType::InlineComponentType : false;
741}
742
743QUrl QQmlType::sourceUrl() const
744{
745 return d ? d->sourceUrl() : QUrl();
746}
747
748int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
749{
750 Q_ASSERT(ok);
751 if (d) {
752 *ok = true;
753
754 d->initEnums(engine);
755
756 int *rv = d->enums.value(key: name);
757 if (rv)
758 return *rv;
759 }
760
761 *ok = false;
762 return -1;
763}
764
765int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
766{
767 Q_ASSERT(ok);
768 if (d) {
769 *ok = true;
770
771 d->initEnums(engine);
772
773 int *rv = d->enums.value(key: name);
774 if (rv)
775 return *rv;
776 }
777
778 *ok = false;
779 return -1;
780}
781
782int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
783{
784 Q_ASSERT(ok);
785 if (d) {
786 *ok = true;
787
788 d->initEnums(engine);
789
790 int *rv = d->enums.value(string: name);
791 if (rv)
792 return *rv;
793 }
794
795 *ok = false;
796 return -1;
797}
798
799int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
800{
801 Q_ASSERT(ok);
802 if (d) {
803 *ok = true;
804
805 d->initEnums(engine);
806
807 int *rv = d->scopedEnumIndex.value(string: name);
808 if (rv)
809 return *rv;
810 }
811
812 *ok = false;
813 return -1;
814}
815
816int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
817{
818 Q_ASSERT(ok);
819 if (d) {
820 *ok = true;
821
822 d->initEnums(engine);
823
824 int *rv = d->scopedEnumIndex.value(key: name);
825 if (rv)
826 return *rv;
827 }
828
829 *ok = false;
830 return -1;
831}
832
833int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
834{
835 Q_UNUSED(engine);
836 Q_ASSERT(ok);
837 *ok = true;
838
839 if (d) {
840 Q_ASSERT(index > -1 && index < d->scopedEnums.size());
841 int *rv = d->scopedEnums.at(i: index)->value(string: name);
842 if (rv)
843 return *rv;
844 }
845
846 *ok = false;
847 return -1;
848}
849
850int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
851{
852 Q_UNUSED(engine);
853 Q_ASSERT(ok);
854 *ok = true;
855
856 if (d) {
857 Q_ASSERT(index > -1 && index < d->scopedEnums.size());
858 int *rv = d->scopedEnums.at(i: index)->value(key: name);
859 if (rv)
860 return *rv;
861 }
862
863 *ok = false;
864 return -1;
865}
866
867int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
868{
869 Q_ASSERT(ok);
870 if (d) {
871 *ok = true;
872
873 d->initEnums(engine);
874
875 int *rv = d->scopedEnumIndex.value(key: QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.size()));
876 if (rv) {
877 int index = *rv;
878 Q_ASSERT(index > -1 && index < d->scopedEnums.size());
879 rv = d->scopedEnums.at(i: index)->value(key: QHashedCStringRef(name.constData(), name.size()));
880 if (rv)
881 return *rv;
882 }
883 }
884
885 *ok = false;
886 return -1;
887}
888
889int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, QStringView scopedEnumName, QStringView name, bool *ok) const
890{
891 Q_ASSERT(ok);
892 if (d) {
893 *ok = true;
894
895 d->initEnums(engine);
896
897 int *rv = d->scopedEnumIndex.value(key: QHashedStringRef(scopedEnumName));
898 if (rv) {
899 int index = *rv;
900 Q_ASSERT(index > -1 && index < d->scopedEnums.size());
901 rv = d->scopedEnums.at(i: index)->value(key: QHashedStringRef(name));
902 if (rv)
903 return *rv;
904 }
905 }
906
907 *ok = false;
908 return -1;
909}
910
911void QQmlType::refHandle(const QQmlTypePrivate *priv)
912{
913 if (priv)
914 priv->addref();
915}
916
917void QQmlType::derefHandle(const QQmlTypePrivate *priv)
918{
919 if (priv)
920 priv->release();
921}
922
923int QQmlType::refCount(const QQmlTypePrivate *priv)
924{
925 if (priv)
926 return priv->count();
927 return -1;
928}
929
930QQmlType QQmlType::containingType() const
931{
932 Q_ASSERT(d && d->regType == QQmlType::RegistrationType::InlineComponentType);
933 auto ret = QQmlType {d->extraData.id->containingType};
934 Q_ASSERT(!ret.isInlineComponentType());
935 return ret;
936}
937
938void QQmlType::createProxy(QObject *instance) const
939{
940 if (!d->metaObjects.isEmpty())
941 (void)new QQmlProxyMetaObject(instance, &d->metaObjects);
942}
943
944QT_END_NAMESPACE
945

source code of qtdeclarative/src/qml/qml/qqmltype.cpp