diff options
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 65 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlscriptparser.cpp | 15 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject.cpp | 243 | ||||
-rw-r--r-- | src/declarative/qml/qmlvmemetaobject_p.h | 59 |
7 files changed, 221 insertions, 166 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index aa2cf84..b04c932 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -63,6 +63,7 @@ #include <private/qmlcontext_p.h> #include <private/qmlcomponent_p.h> #include "parser/qmljsast_p.h" +#include <private/qmlvmemetaobject_p.h> #include "qmlscriptparser_p.h" @@ -1406,6 +1407,8 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias) obj->dynamicSlots.isEmpty()) return true; + QByteArray dynamicData(sizeof(QmlVMEMetaData), (char)0); + QMetaObjectBuilder builder; if (obj->metatype) builder.setClassName(QByteArray(obj->metatype->className()) + "QML"); @@ -1420,41 +1423,65 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias) builder.addClassInfo("DefaultProperty", p.name); QByteArray type; + int propertyType; switch(p.type) { case Object::DynamicProperty::Alias: hasAlias = true; continue; break; case Object::DynamicProperty::Variant: + propertyType = -1; type = "QVariant"; break; case Object::DynamicProperty::Int: + propertyType = QVariant::Int; type = "int"; break; case Object::DynamicProperty::Bool: + propertyType = QVariant::Bool; type = "bool"; break; case Object::DynamicProperty::Real: + propertyType = QVariant::Double; type = "double"; break; case Object::DynamicProperty::String: + propertyType = QVariant::String; type = "QString"; break; case Object::DynamicProperty::Url: + propertyType = QVariant::Url; type = "QUrl"; break; case Object::DynamicProperty::Color: + propertyType = QVariant::Color; type = "QColor"; break; case Object::DynamicProperty::Date: + propertyType = QVariant::Date; type = "QDate"; break; } + ((QmlVMEMetaData *)dynamicData.data())->propertyCount++; + QmlVMEMetaData::PropertyData propertyData = { propertyType }; + dynamicData.append((char *)&propertyData, sizeof(propertyData)); + builder.addSignal(p.name + "Changed()"); builder.addProperty(p.name, type, ii); } + if (preAlias != -1) { + for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { + const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + + if (p.type == Object::DynamicProperty::Alias) { + ((QmlVMEMetaData *)dynamicData.data())->aliasCount++; + compileAlias(builder, dynamicData, obj, p); + } + } + } + for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { const Object::DynamicSignal &s = obj->dynamicSignals.at(ii); QByteArray sig(s.name + "("); @@ -1465,38 +1492,30 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias) sig.append(")"); QMetaMethodBuilder b = builder.addSignal(sig); b.setParameterNames(s.parameterNames); + ((QmlVMEMetaData *)dynamicData.data())->signalCount++; } int slotStart = obj->dynamicSlots.isEmpty()?-1:output->primitives.count(); for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { const Object::DynamicSlot &s = obj->dynamicSlots.at(ii); - builder.addSlot(s.name + "()"); + QByteArray sig(s.name + "("); + for (int jj = 0; jj < s.parameterNames.count(); ++jj) { + if (jj) sig.append(","); + sig.append("QVariant"); + } + sig.append(")"); + QMetaMethodBuilder b = builder.addSlot(sig); + b.setParameterNames(s.parameterNames); + + ((QmlVMEMetaData *)dynamicData.data())->methodCount++; + QmlVMEMetaData::MethodData methodData = { s.parameterNames.count() }; + dynamicData.append((char *)&methodData, sizeof(methodData)); if (preAlias == -1) output->primitives << s.body; } - QByteArray aliasData; - if (preAlias != -1) { - int dynProperties = 0; - QByteArray data; - int propCount = builder.propertyCount(); - int signalCount = builder.methodCount(); - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); - - if (p.type == Object::DynamicProperty::Alias) { - dynProperties++; - compileAlias(builder, data, obj, p); - } - } - aliasData.append((const char *)&dynProperties, sizeof(int)); - aliasData.append((const char *)&propCount, sizeof(int)); - aliasData.append((const char *)&signalCount, sizeof(int)); - aliasData.append(data); - } - if (obj->metatype) builder.setSuperClass(obj->metatype); @@ -1506,7 +1525,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias) if (preAlias != -1) { QmlInstruction &store = output->bytecode[preAlias]; - store.storeMeta.aliasData = output->indexForByteArray(aliasData); + store.storeMeta.aliasData = output->indexForByteArray(dynamicData); qFree(output->synthesizedMetaObjects.at(store.storeMeta.data)); output->synthesizedMetaObjects[store.storeMeta.data] = obj->extObjectData; @@ -1516,7 +1535,7 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj, int preAlias) store.type = QmlInstruction::StoreMetaObject; store.storeMeta.data = output->synthesizedMetaObjects.count() - 1; store.storeMeta.slotData = slotStart; - store.storeMeta.aliasData = -1; + store.storeMeta.aliasData = output->indexForByteArray(dynamicData); store.line = obj->location.start.line; output->bytecode << store; diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 2e7eb69..8daab6a 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -133,7 +133,7 @@ QmlParser::Object::DynamicSlot::DynamicSlot() } QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) -: name(o.name), body(o.body) +: name(o.name), body(o.body), parameterNames(o.parameterNames) { } diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 803c73e..7550870 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -166,6 +166,7 @@ namespace QmlParser QByteArray name; QString body; + QList<QByteArray> parameterNames; }; // The list of dynamic properties diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 1c88018..82f6a60 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -723,20 +723,19 @@ bool ProcessAST::visit(AST::UiSourceElement *node) if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { - if(funDecl->formals) { - QmlError error; - error.setDescription(QCoreApplication::translate("QmlParser","Slot declarations must be parameterless")); - error.setLine(funDecl->lparenToken.startLine); - error.setColumn(funDecl->lparenToken.startColumn); - _parser->_errors << error; - return false; + Object::DynamicSlot slot; + + AST::FormalParameterList *f = funDecl->formals; + while (f) { + slot.parameterNames << f->name->asString().toUtf8(); + f = f->finish(); } QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken); - Object::DynamicSlot slot; slot.name = funDecl->name->asString().toUtf8(); slot.body = body; obj->dynamicSlots << slot; + } else { QmlError error; error.setDescription(QCoreApplication::translate("QmlParser","QmlJS declaration outside Script element")); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 0d88e02..a11caeb 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -239,7 +239,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp case QmlInstruction::StoreMetaObject: { QObject *target = stack.top(); - new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, (instr.storeMeta.aliasData != -1)?datas.at(instr.storeMeta.aliasData):QByteArray(), comp); + new QmlVMEMetaObject(target, synthesizedMetaObjects.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(), comp); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index dc06bc5..6d14689 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -55,10 +55,10 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, const QMetaObject *other, QList<QString> *strData, int slotData, - const QByteArray &alias, + const QmlVMEMetaData *meta, QmlRefCount *rc) -: object(obj), ref(rc), slotData(strData), slotDataIdx(slotData), parent(0), - aliasData(alias), aliases(0), aliasArray(0) +: object(obj), ref(rc), metaData(meta), slotData(strData), + slotDataIdx(slotData), parent(0) { if (ref) ref->addref(); @@ -71,44 +71,18 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject); op->metaObject = this; - if (!aliasData.isEmpty()) { - aliases = (Aliases *)aliasData.constData(); - aliasArray = (AliasArray *)(aliasData.constData() + 3 * sizeof(int)); - aConnected.resize(aliases->aliasCount); - } + propOffset = QAbstractDynamicMetaObject::propertyOffset(); + methodOffset = QAbstractDynamicMetaObject::methodOffset(); - baseProp = propertyOffset(); - baseSig = methodOffset(); - int propCount = propertyCount() - (aliases?aliases->aliasCount:0); - data = new QVariant[propCount - baseProp]; - vTypes.resize(propCount - baseProp); + data = new QVariant[metaData->propertyCount]; + aConnected.resize(metaData->aliasCount); // ### Optimize - for (int ii = baseProp; ii < propCount; ++ii) { - QMetaProperty prop = property(ii); - if ((int)prop.type() != -1) { - data[ii - baseProp] = QVariant((QVariant::Type)prop.userType()); - } else { - vTypes.setBit(ii - baseProp, true); - } + for (int ii = 0; ii < metaData->propertyCount; ++ii) { + int t = (metaData->propertyData() + ii)->propertyType; + if (t != -1) + data[ii] = QVariant((QVariant::Type)t); } - - baseSlot = -1; - slotCount = 0; - for (int ii = baseSig; ii < methodCount(); ++ii) { - QMetaMethod m = method(ii); - if (m.methodType() == QMetaMethod::Slot) { - if (baseSlot == -1) - baseSlot = ii; - } else { - if (baseSlot != -1) { - slotCount = ii - baseSlot; - break; - } - } - } - if(baseSlot != -1 && !slotCount) - slotCount = methodCount() - baseSlot; } QmlVMEMetaObject::~QmlVMEMetaObject() @@ -120,111 +94,146 @@ QmlVMEMetaObject::~QmlVMEMetaObject() delete [] data; } -int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a) +int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) { + int id = _id; if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) { - if (id >= baseProp) { - int propId = id - baseProp; - bool needActivate = false; + if (id >= propOffset) { + id -= propOffset; + + if (id < metaData->propertyCount) { + int t = (metaData->propertyData() + id)->propertyType; + bool needActivate = false; + + if (t == -1) { + + if (c == QMetaObject::ReadProperty) { + *reinterpret_cast<QVariant *>(a[0]) = data[id]; + } else if (c == QMetaObject::WriteProperty) { + needActivate = + (data[id] != *reinterpret_cast<QVariant *>(a[0])); + data[id] = *reinterpret_cast<QVariant *>(a[0]); + } + + } else { + + if (c == QMetaObject::ReadProperty) { + switch(t) { + case QVariant::Int: + *reinterpret_cast<int *>(a[0]) = data[id].toInt(); + break; + case QVariant::Bool: + *reinterpret_cast<bool *>(a[0]) = data[id].toBool(); + break; + case QVariant::Double: + *reinterpret_cast<double *>(a[0]) = data[id].toDouble(); + break; + case QVariant::String: + *reinterpret_cast<QString *>(a[0]) = data[id].toString(); + break; + case QVariant::Url: + *reinterpret_cast<QUrl *>(a[0]) = data[id].toUrl(); + break; + case QVariant::Color: + *reinterpret_cast<QColor *>(a[0]) = data[id].value<QColor>(); + break; + case QVariant::Date: + *reinterpret_cast<QDate *>(a[0]) = data[id].toDate(); + break; + default: + break; + } + + } else if (c == QMetaObject::WriteProperty) { + + QVariant value = QVariant((QVariant::Type)data[id].type(), a[0]); + needActivate = (data[id] != value); + data[id] = value; + } + + } + + if (c == QMetaObject::WriteProperty && needActivate) { + activate(object, methodOffset + id, 0); + } + + return -1; + } + + id -= metaData->propertyCount; + + if (id < metaData->aliasCount) { - if (aliases && propId >= aliases->propCount) { QmlContext *ctxt = qmlContext(object); if (!ctxt) return -1; - int aliasId = propId - aliases->propCount; - AliasArray *d = aliasArray + aliasId; + QmlVMEMetaData::AliasData *d = metaData->aliasData() + id; QmlContextPrivate *ctxtPriv = (QmlContextPrivate *)QObjectPrivate::get(ctxt); - QObject *target = *(QObject **)ctxtPriv->propertyValues[d->contextIdx].data(); + QObject *target = + *(QObject **)ctxtPriv->propertyValues[d->contextIdx].data(); if (!target) return -1; - if (c == QMetaObject::ReadProperty && - !aConnected.testBit(aliasId)) { - - int mySigIdx = baseSig + aliasId + aliases->signalOffset; - QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, mySigIdx); + if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { + int sigIdx = methodOffset + id + metaData->propertyCount; + QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); - QMetaProperty prop = target->metaObject()->property(d->propIdx); + QMetaProperty prop = + target->metaObject()->property(d->propertyIdx); if (prop.hasNotifySignal()) QMetaObject::connect(target, prop.notifySignalIndex(), - object, mySigIdx); - aConnected.setBit(aliasId); - - } - return QMetaObject::metacall(target, c, d->propIdx, a); - - } else if (vTypes.testBit(propId)) { - if (c == QMetaObject::ReadProperty) { - *reinterpret_cast<QVariant *>(a[0]) = data[propId]; - } else if (c == QMetaObject::WriteProperty) { - needActivate = - (data[propId] != *reinterpret_cast<QVariant *>(a[0])); - data[propId] = *reinterpret_cast<QVariant *>(a[0]); + object, sigIdx); + aConnected.setBit(id); } - } else { - if (c == QMetaObject::ReadProperty) { - switch(data[propId].type()) { - case QVariant::Int: - *reinterpret_cast<int *>(a[0]) = data[propId].toInt(); - break; - case QVariant::Bool: - *reinterpret_cast<bool *>(a[0]) = data[propId].toBool(); - break; - case QVariant::Double: - *reinterpret_cast<double *>(a[0]) = data[propId].toDouble(); - break; - case QVariant::String: - *reinterpret_cast<QString *>(a[0]) = data[propId].toString(); - break; - case QVariant::Url: - *reinterpret_cast<QUrl *>(a[0]) = data[propId].toUrl(); - break; - case QVariant::Color: - *reinterpret_cast<QColor *>(a[0]) = data[propId].value<QColor>(); - break; - case QVariant::Date: - *reinterpret_cast<QDate *>(a[0]) = data[propId].toDate(); - break; - default: - qFatal("Unknown type"); - break; - } - } else if (c == QMetaObject::WriteProperty) { + return QMetaObject::metacall(target, c, d->propertyIdx, a); - QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]); - needActivate = (data[propId] != value); - data[propId] = value; - } } + return -1; - if (c == QMetaObject::WriteProperty && needActivate) { - activate(object, baseSig + propId, 0); - } + } - return id; - } } else if(c == QMetaObject::InvokeMetaMethod) { - if (id >= baseSig && (aliases && id >= baseSig + aliases->signalOffset)) { - QMetaObject::activate(object, id, a); - return id; - } else if (id >= baseSig && (baseSlot == -1 || id < baseSlot)) { - QMetaObject::activate(object, id, a); - return id; - } else if (id >= baseSlot && id < (baseSlot + slotCount)) { - int idx = id - baseSlot + slotDataIdx; - QmlContext *ctxt = qmlContext(object); - QmlExpression expr(ctxt, slotData->at(idx), object); - expr.setTrackChange(false); - expr.value(); - return id; + + if (id >= methodOffset) { + + id -= methodOffset; + int plainSignals = metaData->signalCount + metaData->propertyCount + + metaData->aliasCount; + if (id < plainSignals) { + QMetaObject::activate(object, _id, a); + return -1; + } + + id -= plainSignals; + + if (id < metaData->methodCount) { + QString code = slotData->at(id + slotDataIdx); + QmlContext *ctxt = qmlContext(object); + + if (0 == (metaData->methodData() + id)->parameterCount) { + QmlExpression expr(ctxt, code, object); + expr.setTrackChange(false); + expr.value(); + } else { + QmlContext newCtxt(ctxt); + QMetaMethod m = method(_id); + QList<QByteArray> names = m.parameterNames(); + for (int ii = 0; ii < names.count(); ++ii) + newCtxt.setContextProperty(names.at(ii), *(QVariant *)a[ii + 1]); + QmlExpression expr(&newCtxt, code, object); + expr.setTrackChange(false); + expr.value(); + } + } + return -1; } } if (parent) - return parent->metaCall(c, id, a); + return parent->metaCall(c, _id, a); else - return object->qt_metacall(c, id, a); + return object->qt_metacall(c, _id, a); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 45fb33d..6421c3f 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -59,11 +59,45 @@ #include <private/qobject_p.h> QT_BEGIN_NAMESPACE + +struct QmlVMEMetaData +{ + short propertyCount; + short aliasCount; + short signalCount; + short methodCount; + + struct AliasData { + int contextIdx; + int propertyIdx; + }; + + struct PropertyData { + int propertyType; + }; + + struct MethodData { + int parameterCount; + }; + + PropertyData *propertyData() const { + return (PropertyData *)(((const char *)this) + sizeof(QmlVMEMetaData)); + } + + AliasData *aliasData() const { + return (AliasData *)(propertyData() + propertyCount); + } + + MethodData *methodData() const { + return (MethodData *)(aliasData() + propertyCount); + } +}; + class QmlRefCount; class QmlVMEMetaObject : public QAbstractDynamicMetaObject { public: - QmlVMEMetaObject(QObject *, const QMetaObject *, QList<QString> *, int slotData, const QByteArray &aliasData, QmlRefCount * = 0); + QmlVMEMetaObject(QObject *, const QMetaObject *, QList<QString> *, int slotData, const QmlVMEMetaData *data, QmlRefCount * = 0); ~QmlVMEMetaObject(); protected: @@ -72,26 +106,19 @@ protected: private: QObject *object; QmlRefCount *ref; - int baseProp; - int baseSig; - int baseSlot; - int slotCount; + + const QmlVMEMetaData *metaData; + int propOffset; + int methodOffset; + QVariant *data; - QBitArray vTypes; QBitArray aConnected; + QList<QString> *slotData; int slotDataIdx; + QAbstractDynamicMetaObject *parent; - QByteArray aliasData; - struct Aliases { - int aliasCount; - int propCount; - int signalOffset; - } *aliases; - struct AliasArray { - int contextIdx; - int propIdx; - } *aliasArray; + }; QT_END_NAMESPACE |