QDeclarativeInfo::~QDeclarativeInfo() { if (0 == --d->ref) { QList<QDeclarativeError> errors = d->errors; QDeclarativeEngine *engine = 0; if (!d->buffer.isEmpty()) { QDeclarativeError error; QObject *object = const_cast<QObject *>(d->object); if (object) { engine = qmlEngine(d->object); QString typeName; QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject()); if (type) { typeName = QLatin1String(type->qmlTypeName()); int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); if (lastSlash != -1) typeName = typeName.mid(lastSlash+1); } else { typeName = QString::fromUtf8(object->metaObject()->className()); int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); if (marker != -1) typeName = typeName.left(marker); marker = typeName.indexOf(QLatin1String("_QML_")); if (marker != -1) { typeName = typeName.left(marker) + "*"; type = QDeclarativeMetaType::qmlType(QMetaType::type(typeName.toLatin1())); if (type) { typeName = QLatin1String(type->qmlTypeName()); int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); if (lastSlash != -1) typeName = typeName.mid(lastSlash+1); } } } d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": ")); QDeclarativeData *ddata = QDeclarativeData::get(object, false); if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) { error.setUrl(ddata->outerContext->url); error.setLine(ddata->lineNumber); error.setColumn(ddata->columnNumber); } } error.setDescription(d->buffer); errors.prepend(error); } QDeclarativeEnginePrivate::warning(engine, errors); delete d; } }
const QMetaObject *QDeclarativePropertyPrivate::rawMetaObjectForType(QDeclarativeEnginePrivate *engine, int userType) { if (engine) { return engine->rawMetaObjectForType(userType); } else { QDeclarativeType *type = QDeclarativeMetaType::qmlType(userType); return type?type->baseMetaObject():0; } }
void MetaInfoPrivate::typeInfo(const QMetaObject *qMetaObject, QString *typeName, int *majorVersion, int *minorVersion) const { Q_ASSERT(typeName); if (!qMetaObject) return; *typeName = qMetaObject->className(); int majVersion = -1; int minVersion = -1; QDeclarativeType *qmlType = QDeclarativeMetaType::qmlType(qMetaObject); if (qmlType) { if (!qmlType->qmlTypeName().isEmpty()) { *typeName = qmlType->qmlTypeName(); majVersion = qmlType->majorVersion(); minVersion = qmlType->minorVersion(); } } if (majorVersion) *majorVersion = majVersion; if (minorVersion) *minorVersion = minVersion; }
bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePropertyCache::Data &property, const QVariant &value, QDeclarativeContextData *context, WriteFlags flags) { int coreIdx = property.coreIndex; int status = -1; //for dbus if (property.flags & QDeclarativePropertyCache::Data::IsEnumType) { QMetaProperty prop = object->metaObject()->property(property.coreIndex); QVariant v = value; // Enum values come through the script engine as doubles if (value.userType() == QVariant::Double) { double integral; double fractional = modf(value.toDouble(), &integral); if (qFuzzyIsNull(fractional)) v.convert(QVariant::Int); } return writeEnumProperty(prop, coreIdx, object, v, flags); } int propertyType = property.propType; int variantType = value.userType(); QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context); if (propertyType == QVariant::Url) { QUrl u; bool found = false; if (variantType == QVariant::Url) { u = value.toUrl(); found = true; } else if (variantType == QVariant::ByteArray) { u = QUrl(QString::fromUtf8(value.toByteArray())); found = true; } else if (variantType == QVariant::String) { u = QUrl(value.toString()); found = true; } if (!found) return false; if (context && u.isRelative() && !u.isEmpty()) u = context->resolvedUrl(u); int status = -1; void *argv[] = { &u, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); } else if (variantType == propertyType) { void *a[] = { (void *)value.constData(), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (qMetaTypeId<QVariant>() == propertyType) { void *a[] = { (void *)&value, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (property.flags & QDeclarativePropertyCache::Data::IsQObjectDerived) { const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType()); if (!valMo) return false; QObject *o = *(QObject **)value.constData(); const QMetaObject *propMo = rawMetaObjectForType(enginePriv, propertyType); if (o) valMo = o->metaObject(); if (canConvert(valMo, propMo)) { void *args[] = { &o, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args); } else if (!o && canConvert(propMo, valMo)) { // In the case of a null QObject, we assign the null if there is // any change that the null variant type could be up or down cast to // the property type. void *args[] = { &o, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args); } else { return false; } } else if (property.flags & QDeclarativePropertyCache::Data::IsQList) { const QMetaObject *listType = 0; if (enginePriv) { listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType)); } else { QDeclarativeType *type = QDeclarativeMetaType::qmlType(QDeclarativeMetaType::listType(property.propType)); if (!type) return false; listType = type->baseMetaObject(); } if (!listType) return false; QDeclarativeListProperty<void> prop; void *args[] = { &prop, 0 }; QMetaObject::metacall(object, QMetaObject::ReadProperty, coreIdx, args); if (!prop.clear) return false; prop.clear(&prop); if (value.userType() == qMetaTypeId<QList<QObject *> >()) { const QList<QObject *> &list = qvariant_cast<QList<QObject *> >(value); for (int ii = 0; ii < list.count(); ++ii) { QObject *o = list.at(ii); if (o && !canConvert(o->metaObject(), listType)) o = 0; prop.append(&prop, (void *)o); } } else { QObject *o = enginePriv?enginePriv->toQObject(value):QDeclarativeMetaType::toQObject(value); if (o && !canConvert(o->metaObject(), listType)) o = 0; prop.append(&prop, (void *)o); } } else { Q_ASSERT(variantType != propertyType); QVariant v = value; if (v.convert((QVariant::Type)propertyType)) { void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) { QDeclarativeMetaType::StringConverter con = QDeclarativeMetaType::customStringConverter(propertyType); if (!con) return false; QVariant v = con(value.toString()); if (v.userType() == propertyType) { void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } } else if (variantType == QVariant::String) { bool ok = false; QVariant v = QDeclarativeStringConverters::variantFromString(value.toString(), propertyType, &ok); if (!ok) return false; void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else { return false; } } return true; }
void QJnextMainLoop::createObject(QVariantList& args, QByteArray* result) { uint id = idBase++; // this will OWN the backing char array QByteArray param = args.takeFirst().toByteArray(); QByteArray ns(param); QByteArray ver = QtBridge::takeLastParam(ns, "@"); if (ver.size() == 0) ver = "1.0"; QByteArray cls = QtBridge::takeLastParam(ns, "."); QString qmlcls = QString(ns) + "/" + cls; QObject *& object = objects[id]; if (object != NULL) { *result = "Error object already exists for id" + QByteArray::number(id); qWarning() << *result; return; } #ifdef DEBUG_QJnextMainLoop qDebug() << "[QJnextMainLoop]\tQDeclarative" << "import " + ns + " " + ver + "; " + cls + " {}"; #endif QDeclarativeComponent component(declarativeEngine, this); component.setData( "import " + ns + " " + ver + "; import QtQuick 1.0; QtObject {}", QUrl()); if (component.isError() || !component.isReady()) { qWarning() << "COMPONENT ERROR" << component.errorString(); } int majorVersion = -1, minorVersion = -1; QDeclarativeType * dtype = NULL; QString scls = cls; QList<QDeclarativeType*> types = QDeclarativeMetaType::qmlTypes(); foreach(QDeclarativeType* type, types) { if (ns == type->module()) { QString qmlType = QString::fromLatin1(type->qmlTypeName()); if (qmlcls.compare(qmlType, Qt::CaseInsensitive) == 0) { if (type->majorVersion() > majorVersion && type->minorVersion() > minorVersion) { majorVersion = type->majorVersion(); minorVersion = type->minorVersion(); dtype = type; } } } } if (dtype == NULL && ns == "bb" && cls == "Application") { object = bb::Application::instance(); object->setUserData(userDataId, new QJnextUserData(id)); goto end_createObject; } if (dtype == NULL) { *result = "No such Type " + cls + " in namespace " + ns; qWarning() << *result; return; } else if (!dtype->isCreatable()) { *result = "Class " + ns + "." + cls + " is not creatable: " + dtype->noCreationReason().toLatin1(); qWarning() << *result; return; } #ifdef DEBUG_QJnextMainLoop qDebug() << "[QJnextMainLoop]\t" << dtype->typeId() << dtype->typeName() << QString("%1.%2").arg(QString::number(dtype->majorVersion())).arg( QString::number(dtype->minorVersion())); #endif object = dtype->create(); if (!object) { qWarning() << "COMPONENT.CREATE ERROR"; *result = "Error creating component"; return; } object->setUserData(userDataId, new QJnextUserData(id)); object->setParent(this); end_createObject: *result = QByteArray::number(id); #ifdef DEBUG_QJnextMainLoop qDebug() << "[QJnextMainLoop]\tCreated object" << id; #endif }
void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDebugObjectReference &oref, bool recursive) const { const QMetaObject *meta = o->metaObject(); QDeclarativeType *type = QDeclarativeMetaType::qmlType(meta); QString className = type ? QString(type->qmlTypeName()) : QString(meta->className()); className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); QCOMPARE(oref.debugId(), QDeclarativeDebugService::idForObject(o)); QCOMPARE(oref.name(), o->objectName()); QCOMPARE(oref.className(), className); QCOMPARE(oref.contextDebugId(), QDeclarativeDebugService::idForObject(qmlContext(o))); const QObjectList &children = o->children(); for (int i=0; i<children.count(); i++) { QObject *child = children[i]; if (!qmlContext(child)) continue; int debugId = QDeclarativeDebugService::idForObject(child); QVERIFY(debugId >= 0); QDeclarativeDebugObjectReference cref; foreach (const QDeclarativeDebugObjectReference &ref, oref.children()) { if (ref.debugId() == debugId) { cref = ref; break; } } QVERIFY(cref.debugId() >= 0); if (recursive) recursiveObjectTest(child, cref, true); } foreach (const QDeclarativeDebugPropertyReference &p, oref.properties()) { QCOMPARE(p.objectDebugId(), QDeclarativeDebugService::idForObject(o)); // signal properties are fake - they are generated from QDeclarativeBoundSignal children if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) { QVERIFY(p.value().toString().startsWith('{') && p.value().toString().endsWith('}')); QVERIFY(p.valueTypeName().isEmpty()); QVERIFY(p.binding().isEmpty()); QVERIFY(!p.hasNotifySignal()); continue; } QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData())); QCOMPARE(p.name(), QString::fromUtf8(pmeta.name())); if (pmeta.type() > 0 && pmeta.type() < QVariant::UserType) // TODO test complex types QCOMPARE(p.value(), pmeta.read(o)); if (p.name() == "parent") QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QDeclarativeItem*"); else QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName())); QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::binding(QDeclarativeProperty(o, p.name())); if (binding) QCOMPARE(binding->expression(), p.binding()); QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal()); QVERIFY(pmeta.isValid()); } }