QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObject *metaObject, const QString &property) { Q_ASSERT(metaObject); QDeclarativePropertyCache::Data rv; { const QMetaObject *cmo = metaObject; while (cmo) { int idx = metaObject->indexOfProperty(property.toUtf8()); if (idx != -1) { QMetaProperty p = metaObject->property(idx); if (p.isScriptable()) { rv.load(metaObject->property(idx)); if (!isDynamicMetaObject(cmo)) rv.flags |= Data::IsDirect; return rv; } else { while (cmo && cmo->propertyOffset() >= idx) cmo = cmo->superClass(); } } else { cmo = 0; } } } int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); QStringRef methodNameRef = methodName.leftRef(parenIdx); if (methodNameRef == property) { rv.load(m); if (!isDynamicMetaObject(m.enclosingMetaObject())) rv.flags |= Data::IsDirect; return rv; } } return rv; }
/*! * \internal * * Find the most derived metaobject that doesn't have a dynamic * metaobject farther up the chain. * TODO: Add support to QMetaObject to explicitly say if it's a dynamic * or static metaobject so we don't need this logic */ const QMetaObject *QNodePrivate::findStaticMetaObject(const QMetaObject *metaObject) { const QMetaObject *lastStaticMetaobject = nullptr; auto mo = metaObject; while (mo) { const bool dynamicMetaObject = isDynamicMetaObject(mo); if (dynamicMetaObject) lastStaticMetaobject = nullptr; if (!dynamicMetaObject && !lastStaticMetaobject) lastStaticMetaobject = mo; mo = mo->superClass(); } Q_ASSERT(lastStaticMetaobject); return lastStaticMetaobject; }
void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, int revision, Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { Q_UNUSED(revision); qPersistentDispose(constructor); // Now invalid bool dynamicMetaObject = isDynamicMetaObject(metaObject); allowedRevisionCache.append(0); int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); methodIndexCache.resize(methodCount - methodIndexCacheStart); for (int ii = methodOffset; ii < methodCount; ++ii) { QMetaMethod m = metaObject->method(ii); if (m.access() == QMetaMethod::Private) continue; // Extract method name const char *signature = m.signature(); const char *cptr = signature; while (*cptr != '(') { Q_ASSERT(*cptr != 0); ++cptr; } QString str = dynamicMetaObject?QString::fromUtf8(signature, cptr - signature): QString::fromLatin1(signature, cptr - signature); QHashedString methodName(str); Data *data = &methodIndexCache[ii - methodIndexCacheStart]; data->lazyLoad(m); if (data->isSignal()) data->flags |= signalFlags; else data->flags |= methodFlags; if (!dynamicMetaObject) data->flags |= Data::IsDirect; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (Data **old = stringCache.value(methodName)) { // We only overload methods in the same class, exactly like C++ if ((*old)->flags & Data::IsFunction && (*old)->coreIndex >= methodOffset) data->relatedIndex = (*old)->coreIndex; data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); data->overrideIndex = (*old)->coreIndex; } stringCache.insert(methodName, data); } int propCount = metaObject->propertyCount(); int propOffset = metaObject->propertyOffset(); propertyIndexCache.resize(propCount - propertyIndexCacheStart); for (int ii = propOffset; ii < propCount; ++ii) { QMetaProperty p = metaObject->property(ii); if (!p.isScriptable()) continue; QString str = dynamicMetaObject?QString::fromUtf8(p.name()): QString::fromLatin1(p.name()); QHashedString propName(str); Data *data = &propertyIndexCache[ii - propertyIndexCacheStart]; data->lazyLoad(p, engine); data->flags |= propertyFlags; if (!dynamicMetaObject) data->flags |= Data::IsDirect; data->metaObjectOffset = allowedRevisionCache.count() - 1; if (Data **old = stringCache.value(propName)) { data->overrideIndexIsProperty = !bool((*old)->flags & Data::IsFunction); data->overrideIndex = (*old)->coreIndex; } stringCache.insert(propName, data); } }