summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qmlcompiler.cpp65
-rw-r--r--src/declarative/qml/qmlparser.cpp2
-rw-r--r--src/declarative/qml/qmlparser_p.h1
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp15
-rw-r--r--src/declarative/qml/qmlvme.cpp2
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp243
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h59
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