void collectReachableMetaObjects(const QMetaObject *meta, QSet<const QMetaObject *> *metas, bool extended = false) { if (! meta || metas->contains(meta)) return; // dynamic meta objects can break things badly // but extended types are usually fine const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate *>(meta->d.data); if (extended || !(mop->flags & DynamicMetaObject)) metas->insert(meta); collectReachableMetaObjects(meta->superClass(), metas); }
QSet<const QMetaObject *> collectReachableMetaObjects(const QString &importCode, QDeclarativeEngine *engine) { QSet<const QMetaObject *> metas; metas.insert(FriendlyQObject::qtMeta()); QHash<QByteArray, QSet<QByteArray> > extensions; foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) { qmlTypesByCppName[ty->metaObject()->className()].insert(ty); if (ty->isExtendedType()) { extensions[ty->typeName()].insert(ty->metaObject()->className()); } collectReachableMetaObjects(ty, &metas); }
// find even more QMetaObjects by instantiating QML types and running // over the instances foreach (QQmlType *ty, QQmlMetaType::qmlTypes()) { if (skip.contains(ty)) continue; if (ty->isExtendedType()) continue; if (!ty->isCreatable()) continue; if (ty->typeName() == "QQmlComponent") continue; QString tyName = ty->qmlTypeName(); tyName = tyName.mid(tyName.lastIndexOf(QLatin1Char('/')) + 1); if (tyName.isEmpty()) continue; inObjectInstantiation = tyName; QObject *object = 0; if (ty->isSingleton()) { QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo(); if (siinfo->qobjectCallback) { siinfo->init(engine); collectReachableMetaObjects(object, &metas); object = siinfo->qobjectApi(engine); } else { inObjectInstantiation.clear(); continue; // we don't handle QJSValue singleton types. } } else { object = ty->create(); } inObjectInstantiation.clear(); if (object) collectReachableMetaObjects(object, &metas); else qWarning() << "Could not create" << tyName; }
void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *metas) { if (! object) return; const QMetaObject *meta = object->metaObject(); qDebug() << "Processing object" << meta->className(); collectReachableMetaObjects(meta, metas); for (int index = 0; index < meta->propertyCount(); ++index) { QMetaProperty prop = meta->property(index); if (QDeclarativeMetaType::isQObject(prop.userType())) { qDebug() << " Processing property" << prop.name(); currentProperty = QString("%1::%2").arg(meta->className(), prop.name()); // if the property was not initialized during construction, // accessing a member of oo is going to cause a segmentation fault QObject *oo = QDeclarativeMetaType::toQObject(prop.read(object)); if (oo && !metas->contains(oo->metaObject())) collectReachableMetaObjects(oo, metas); currentProperty.clear(); } } }
QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const QList<QQmlType *> &skip = QList<QQmlType *>()) { QSet<const QMetaObject *> metas; metas.insert(FriendlyQObject::qtMeta()); QHash<QByteArray, QSet<QByteArray> > extensions; foreach (const QQmlType *ty, QQmlMetaType::qmlTypes()) { if (!ty->isComposite()) { qmlTypesByCppName[ty->metaObject()->className()].insert(ty); if (ty->isExtendedType()) extensions[ty->typeName()].insert(ty->metaObject()->className()); collectReachableMetaObjects(ty, &metas); } else { qmlTypesByCompositeName[ty->elementName()] = ty; } } // Adjust exports of the base object if there are extensions. // For each export of a base object there can be a single extension object overriding it. // Example: QDeclarativeGraphicsWidget overrides the QtQuick/QGraphicsWidget export // of QGraphicsWidget. foreach (const QByteArray &baseCpp, extensions.keys()) { QSet<const QQmlType *> baseExports = qmlTypesByCppName.value(baseCpp); const QSet<QByteArray> extensionCppNames = extensions.value(baseCpp); foreach (const QByteArray &extensionCppName, extensionCppNames) { const QSet<const QQmlType *> extensionExports = qmlTypesByCppName.value(extensionCppName); // remove extension exports from base imports // unfortunately the QQmlType pointers don't match, so can't use QSet::subtract QSet<const QQmlType *> newBaseExports; foreach (const QQmlType *baseExport, baseExports) { bool match = false; foreach (const QQmlType *extensionExport, extensionExports) { if (baseExport->qmlTypeName() == extensionExport->qmlTypeName() && baseExport->majorVersion() == extensionExport->majorVersion() && baseExport->minorVersion() == extensionExport->minorVersion()) { match = true; break; } } if (!match) newBaseExports.insert(baseExport); } baseExports = newBaseExports; } qmlTypesByCppName[baseCpp] = baseExports; }
void collectReachableMetaObjects(const QDeclarativeType *ty, QSet<const QMetaObject *> *metas) { collectReachableMetaObjects(ty->metaObject(), metas); if (ty->attachedPropertiesType()) collectReachableMetaObjects(ty->attachedPropertiesType(), metas); }
void collectReachableMetaObjects(const QQmlType *ty, QSet<const QMetaObject *> *metas) { collectReachableMetaObjects(ty->metaObject(), metas, ty->isExtendedType()); if (ty->attachedPropertiesType()) collectReachableMetaObjects(ty->attachedPropertiesType(), metas); }