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