From 1b6e74a2bf4d4b1470e4e6447995cb286520f271 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 15:54:48 +1000 Subject: Very basic slot declaration support Currently only parameterless slots are supported. They are declared inline with the object: Rect { function mySlot() { print("Hello world!"); } } --- src/declarative/qml/qmlcompiler.cpp | 17 +++- src/declarative/qml/qmlcompiler_p.h | 2 +- src/declarative/qml/qmlinstruction.cpp | 2 +- src/declarative/qml/qmlinstruction_p.h | 1 + src/declarative/qml/qmlvme.cpp | 2 +- src/declarative/qml/qmlvmemetaobject.cpp | 132 +++++++++++++++++++------------ src/declarative/qml/qmlvmemetaobject_p.h | 6 +- 7 files changed, 106 insertions(+), 56 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index b8f3921..d4003ab 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -545,7 +545,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) create.create.type = obj->type; output->bytecode << create; - COMPILE_CHECK(compileDynamicPropertiesAndSignals(obj)); + COMPILE_CHECK(compileDynamicMeta(obj)); if (obj->type != -1) { if (output->types.at(obj->type).component) { @@ -1212,10 +1212,12 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, return true; } -bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj) +bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) { // ### FIXME - Check that there is only one default property etc. - if (obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty()) + if (obj->dynamicProperties.isEmpty() && + obj->dynamicSignals.isEmpty() && + obj->dynamicSlots.isEmpty()) return true; QMetaObjectBuilder builder; @@ -1263,6 +1265,14 @@ bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj) builder.addSignal(s.name + "()"); } + 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 + "()"); + output->primitives << s.body; + } + if (obj->metatype) builder.setSuperClass(obj->metatype); @@ -1272,6 +1282,7 @@ bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj) QmlInstruction store; store.type = QmlInstruction::StoreMetaObject; store.storeMeta.data = output->mos.count() - 1; + store.storeMeta.slotData = slotStart; store.line = obj->line; output->bytecode << store; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 4acdcfa..e2b8388 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -163,7 +163,7 @@ private: QmlParser::Value *value, int ctxt); - bool compileDynamicPropertiesAndSignals(QmlParser::Object *obj); + bool compileDynamicMeta(QmlParser::Object *obj); void compileBinding(const QString &, QmlParser::Property *prop, int ctxt, const QMetaObject *, qint64); diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 52677c2..0617913 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -68,7 +68,7 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count; break; case QmlInstruction::StoreMetaObject: - qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data; + qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData; break; case QmlInstruction::StoreReal: qWarning() << idx << "\t" << line << "\t" << "STORE_REAL\t\t" << instr->storeReal.propertyIndex << "\t" << instr->storeReal.value; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 462f9e4..01bdfdd 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -177,6 +177,7 @@ public: } create; struct { int data; + int slotData; } storeMeta; struct { int value; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index ad3d1d5..ee7a881 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -320,7 +320,7 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in QFxCompilerTimer cc; #endif QObject *target = stack.top(); - new QmlVMEMetaObject(target, mos.at(instr.storeMeta.data), comp); + new QmlVMEMetaObject(target, mos.at(instr.storeMeta.data), &comp->primitives, instr.storeMeta.slotData, comp); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index f7d2635..58708cf 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -44,13 +44,18 @@ #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, - const QMetaObject *other, - QmlRefCount *rc) -: object(obj), ref(rc) + const QMetaObject *other, + QList *strData, + int slotData, + QmlRefCount *rc) +: object(obj), ref(rc), slotData(strData), slotDataIdx(slotData) { if (ref) ref->addref(); @@ -64,6 +69,7 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, data = new QVariant[propertyCount() - baseProp]; vTypes.resize(propertyCount() - baseProp); + // ### Optimize for (int ii = baseProp; ii < propertyCount(); ++ii) { QMetaProperty prop = property(ii); if ((int)prop.type() != -1) { @@ -72,6 +78,23 @@ QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj, vTypes.setBit(ii - baseProp, true); } } + + 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() @@ -83,58 +106,69 @@ QmlVMEMetaObject::~QmlVMEMetaObject() int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a) { - if (id >= baseProp) { - int propId = id - baseProp; - bool needActivate = false; + if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) { + if (id >= baseProp) { + int propId = id - baseProp; + bool needActivate = false; - if (vTypes.testBit(propId)) { - if (c == QMetaObject::ReadProperty) { - *reinterpret_cast(a[0]) = data[propId]; - } else if (c == QMetaObject::WriteProperty) { - needActivate = - (data[propId] != *reinterpret_cast(a[0])); - data[propId] = *reinterpret_cast(a[0]); - } - } else { - if (c == QMetaObject::ReadProperty) { - switch(data[propId].type()) { - case QVariant::Int: - *reinterpret_cast(a[0]) = data[propId].toInt(); - break; - case QVariant::Bool: - *reinterpret_cast(a[0]) = data[propId].toBool(); - break; - case QVariant::Double: - *reinterpret_cast(a[0]) = data[propId].toDouble(); - break; - case QVariant::String: - *reinterpret_cast(a[0]) = data[propId].toString(); - break; - case QVariant::Color: - *reinterpret_cast(a[0]) = data[propId].value(); - break; - case QVariant::Date: - *reinterpret_cast(a[0]) = data[propId].toDate(); - break; - default: - qFatal("Unknown type"); - break; + if (vTypes.testBit(propId)) { + if (c == QMetaObject::ReadProperty) { + *reinterpret_cast(a[0]) = data[propId]; + } else if (c == QMetaObject::WriteProperty) { + needActivate = + (data[propId] != *reinterpret_cast(a[0])); + data[propId] = *reinterpret_cast(a[0]); } - } else if (c == QMetaObject::WriteProperty) { + } else { + if (c == QMetaObject::ReadProperty) { + switch(data[propId].type()) { + case QVariant::Int: + *reinterpret_cast(a[0]) = data[propId].toInt(); + break; + case QVariant::Bool: + *reinterpret_cast(a[0]) = data[propId].toBool(); + break; + case QVariant::Double: + *reinterpret_cast(a[0]) = data[propId].toDouble(); + break; + case QVariant::String: + *reinterpret_cast(a[0]) = data[propId].toString(); + break; + case QVariant::Color: + *reinterpret_cast(a[0]) = data[propId].value(); + break; + case QVariant::Date: + *reinterpret_cast(a[0]) = data[propId].toDate(); + break; + default: + qFatal("Unknown type"); + break; + } + } else if (c == QMetaObject::WriteProperty) { - QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]); - needActivate = (data[propId] != value); - data[propId] = value; + QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]); + needActivate = (data[propId] != value); + data[propId] = value; + } } - } - if (c == QMetaObject::WriteProperty && needActivate) { - activate(object, baseSig + propId, 0); - } + if (c == QMetaObject::WriteProperty && needActivate) { + activate(object, baseSig + propId, 0); + } - return id; - } else { - return object->qt_metacall(c, id, a); + return id; + } + } else if(c == QMetaObject::InvokeMetaMethod) { + 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; + } } + + 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 3fb1c46..d8ed242 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -52,7 +52,7 @@ class QmlRefCount; class QmlVMEMetaObject : public QAbstractDynamicMetaObject { public: - QmlVMEMetaObject(QObject *, const QMetaObject *, QmlRefCount * = 0); + QmlVMEMetaObject(QObject *, const QMetaObject *, QList *, int slotData, QmlRefCount * = 0); ~QmlVMEMetaObject(); protected: @@ -63,8 +63,12 @@ private: QmlRefCount *ref; int baseProp; int baseSig; + int baseSlot; + int slotCount; QVariant *data; QBitArray vTypes; + QList *slotData; + int slotDataIdx; }; QT_END_NAMESPACE -- cgit v0.12