diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-15 12:56:21 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-15 12:56:47 (GMT) |
commit | 5be67ef5ad9b2f6020ffe47eecc9fd3338957bb7 (patch) | |
tree | 3d2422fe01d518848a0a2df0639a199abd756be4 /src/declarative | |
parent | f3aa702372e749b707ce1d6746dfc2e2aba31306 (diff) | |
download | Qt-5be67ef5ad9b2f6020ffe47eecc9fd3338957bb7.zip Qt-5be67ef5ad9b2f6020ffe47eecc9fd3338957bb7.tar.gz Qt-5be67ef5ad9b2f6020ffe47eecc9fd3338957bb7.tar.bz2 |
Implement SetProperties as a custom parser
This will allow us to remove all "Assign*" style instructions from the QML compiler and have it depend only on static data.
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qmlcustomparser.cpp | 28 | ||||
-rw-r--r-- | src/declarative/qml/qmlcustomparser_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser_p.h | 1 | ||||
-rw-r--r-- | src/declarative/util/qmllistmodel.cpp | 6 | ||||
-rw-r--r-- | src/declarative/util/qmlsetproperties.cpp | 314 | ||||
-rw-r--r-- | src/declarative/util/qmlsetproperties.h | 10 |
6 files changed, 228 insertions, 133 deletions
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp index e864df9..a60f783 100644 --- a/src/declarative/qml/qmlcustomparser.cpp +++ b/src/declarative/qml/qmlcustomparser.cpp @@ -120,6 +120,7 @@ QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root) return rootNode; } +#include <QtCore/qdebug.h> QmlCustomParserProperty QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) { @@ -127,20 +128,23 @@ QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) prop.d->name = p->name; prop.d->isList = (p->values.count() > 1); - for(int ii = 0; ii < p->values.count(); ++ii) { - Value *v = p->values.at(ii); + if (p->value) { + QmlCustomParserNode node = fromObject(p->value); + QList<QmlCustomParserProperty> props = node.properties(); + for (int ii = 0; ii < props.count(); ++ii) + prop.d->values << QVariant::fromValue(props.at(ii)); + } else { + for(int ii = 0; ii < p->values.count(); ++ii) { + Value *v = p->values.at(ii); + + if(v->object) { + QmlCustomParserNode node = fromObject(v->object); + prop.d->values << QVariant::fromValue(node); + } else { + prop.d->values << QVariant::fromValue(v->value); + } - // We skip fetched properties for now - if(v->object && v->object->type == -1) - continue; - - if(v->object) { - QmlCustomParserNode node = fromObject(v->object); - prop.d->values << QVariant::fromValue(node); - } else { - prop.d->values << QVariant::fromValue(v->primitive()); } - } return prop; diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h index e4e6089..fd780d6 100644 --- a/src/declarative/qml/qmlcustomparser_p.h +++ b/src/declarative/qml/qmlcustomparser_p.h @@ -65,6 +65,8 @@ public: QByteArray name() const; bool isList() const; + // Will be one of QmlParser::Variant, QmlCustomParserProperty or + // QmlCustomParserNode QList<QVariant> assignedValues() const; private: diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 5cc810e..95b21e6 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -272,6 +272,7 @@ namespace QmlParser void dump(int = 0) const; }; } +Q_DECLARE_METATYPE(QmlParser::Variant); QT_END_NAMESPACE diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 8184bda..80eb9c3 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -43,6 +43,7 @@ #include <QtCore/qstack.h> #include <QXmlStreamReader> #include <private/qmlcustomparser_p.h> +#include <private/qmlparser_p.h> #include "qmlopenmetaobject.h" #include <qmlcontext.h> #include <qmlbindablevalue.h> @@ -414,8 +415,11 @@ bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList } else { + QmlParser::Variant variant = + qvariant_cast<QmlParser::Variant>(value); + int ref = data.count(); - QByteArray d = value.toString().toLatin1(); + QByteArray d = variant.asScript().toLatin1(); d.append('\0'); data.append(d); diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index 9b5a58e..9a1095c 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -44,61 +44,12 @@ #include "qmlsetproperties.h" #include <QtCore/qdebug.h> #include <QtDeclarative/qmlinfo.h> +#include <private/qmlcustomparser_p.h> +#include <private/qmlparser_p.h> +#include <QtDeclarative/qmlexpression.h> QT_BEGIN_NAMESPACE -class QmlSetPropertiesMetaObject : public QmlOpenMetaObject -{ -public: - QmlSetPropertiesMetaObject(QObject *); - -protected: - virtual void propertyRead(int); - virtual void propertyWrite(int); -}; - -class QmlSetPropertiesProxyObject : public QObject -{ -Q_OBJECT -public: - QmlSetPropertiesProxyObject(QObject *); - - QmlSetPropertiesMetaObject *fxMetaObject() const { return _mo; } -private: - QmlSetPropertiesMetaObject *_mo; -}; - -QmlSetPropertiesProxyObject::QmlSetPropertiesProxyObject(QObject *parent) -: QObject(parent), _mo(new QmlSetPropertiesMetaObject(this)) -{ -} - -QmlSetPropertiesMetaObject::QmlSetPropertiesMetaObject(QObject *obj) -: QmlOpenMetaObject(obj) -{ -} - -void QmlSetPropertiesMetaObject::propertyRead(int id) -{ - if (!value(id).isValid()) - setValue(id, QVariant::fromValue((QObject *)new QmlSetPropertiesProxyObject(object()))); - - QmlOpenMetaObject::propertyRead(id); -} - -void QmlSetPropertiesMetaObject::propertyWrite(int id) -{ - if (value(id).userType() == qMetaTypeId<QObject *>()) { - QObject *val = qvariant_cast<QObject *>(value(id)); - QmlSetPropertiesProxyObject *proxy = qobject_cast<QmlSetPropertiesProxyObject *>(val); - if (proxy) { - setValue(id, QVariant()); - delete proxy; - } - } - QmlOpenMetaObject::propertyWrite(id); -} - /*! \qmlclass SetProperties QmlSetProperties \brief The SetProperties element describes new property values for a state. @@ -149,109 +100,248 @@ void QmlSetPropertiesMetaObject::propertyWrite(int id) \sa QmlSetProperty */ +/*! + \qmlproperty Object SetProperties::target + This property holds the object that the properties to change belong to +*/ + +/*! + \property QmlSetProperties::target + \brief the object that the properties to change belong to +*/ class QmlSetPropertiesPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlSetProperties) public: - QmlSetPropertiesPrivate() : obj(0), mo(0) {} + QmlSetPropertiesPrivate() : object(0), decoded(true) {} - QObject *obj; - QmlSetPropertiesMetaObject *mo; + QObject *object; + QByteArray data; + bool decoded; + void decode(); + + QList<QPair<QByteArray, QVariant> > properties; + QList<QPair<QByteArray, QmlExpression *> > expressions; + + QmlMetaProperty property(const QByteArray &); }; -QML_DEFINE_TYPE(QmlSetProperties,SetProperties); -QmlSetProperties::QmlSetProperties() - : QmlStateOperation(*(new QmlSetPropertiesPrivate)) +class QmlSetPropertiesParser : public QmlCustomParser { - Q_D(QmlSetProperties); - d->mo = new QmlSetPropertiesMetaObject(this); +public: + void compileList(QList<QPair<QByteArray, QVariant> > &list, const QByteArray &pre, const QmlCustomParserProperty &prop); + + virtual QByteArray compile(const QList<QmlCustomParserProperty> &, bool *ok); + virtual void setCustomData(QObject *, const QByteArray &); +}; + +void +QmlSetPropertiesParser::compileList(QList<QPair<QByteArray, QVariant> > &list, + const QByteArray &pre, + const QmlCustomParserProperty &prop) +{ + QByteArray propName = pre + prop.name(); + + QList<QVariant> values = prop.assignedValues(); + for (int ii = 0; ii < values.count(); ++ii) { + const QVariant &value = values.at(ii); + + if (value.userType() == qMetaTypeId<QmlCustomParserNode>()) { + continue; + } else if(value.userType() == qMetaTypeId<QmlCustomParserProperty>()) { + + QmlCustomParserProperty prop = + qvariant_cast<QmlCustomParserProperty>(value); + QByteArray pre = propName + "."; + compileList(list, pre, prop); + + } else { + list << qMakePair(propName, value); + } + } } -QmlSetProperties::QmlSetProperties(QObject *parent) - : QmlStateOperation(*(new QmlSetPropertiesPrivate), parent) +QByteArray +QmlSetPropertiesParser::compile(const QList<QmlCustomParserProperty> &props, + bool *ok) { - Q_D(QmlSetProperties); - d->mo = new QmlSetPropertiesMetaObject(this); + *ok = true; + + QList<QPair<QByteArray, QVariant> > data; + for(int ii = 0; ii < props.count(); ++ii) + compileList(data, QByteArray(), props.at(ii)); + + QByteArray rv; + QDataStream ds(&rv, QIODevice::WriteOnly); + + ds << data.count(); + for(int ii = 0; ii < data.count(); ++ii) { + QmlParser::Variant v = qvariant_cast<QmlParser::Variant>(data.at(ii).second); + QVariant var; + bool isScript = v.isScript(); + switch(v.type()) { + case QmlParser::Variant::Boolean: + var = QVariant(v.asBoolean()); + break; + case QmlParser::Variant::Number: + var = QVariant(v.asNumber()); + break; + case QmlParser::Variant::String: + var = QVariant(v.asString()); + break; + case QmlParser::Variant::Invalid: + case QmlParser::Variant::Script: + var = QVariant(v.asScript()); + break; + } + + ds << data.at(ii).first << isScript << var; + } + + return rv; } -QmlSetProperties::~QmlSetProperties() +void QmlSetPropertiesPrivate::decode() { + if (decoded) + return; + + QDataStream ds(&data, QIODevice::ReadOnly); + + int count; + ds >> count; + for (int ii = 0; ii < count; ++ii) { + QByteArray name; + bool isScript; + QVariant data; + ds >> name; + ds >> isScript; + ds >> data; + + if (isScript) { + QmlExpression *expression = new QmlExpression(qmlContext(object), data.toString(), object); + expression->setTrackChange(false); + expressions << qMakePair(name, expression); + } else { + properties << qMakePair(name, data); + } + } + + decoded = true; + data.clear(); } -/*! - \qmlproperty Object SetProperties::target - This property holds the object that the properties to change belong to -*/ +void QmlSetPropertiesParser::setCustomData(QObject *object, + const QByteArray &data) +{ + QmlSetPropertiesPrivate *p = + static_cast<QmlSetPropertiesPrivate *>(QObjectPrivate::get(object)); + p->data = data; + p->decoded = false; +} -/*! - \property QmlSetProperties::target - \brief the object that the properties to change belong to -*/ -QObject *QmlSetProperties::object() +QmlSetProperties::QmlSetProperties() +: QmlStateOperation(*(new QmlSetPropertiesPrivate)) +{ +} + +QmlSetProperties::~QmlSetProperties() { Q_D(QmlSetProperties); - return d->obj; + for(int ii = 0; ii < d->expressions.count(); ++ii) + delete d->expressions.at(ii).second; +} + +QObject *QmlSetProperties::object() const +{ + Q_D(const QmlSetProperties); + return d->object; } void QmlSetProperties::setObject(QObject *o) { Q_D(QmlSetProperties); - d->obj = o; + d->object = o; } -QmlSetProperties::ActionList -QmlSetProperties::doAction(QmlSetPropertiesMetaObject *metaObject, - QObject *object) +QmlMetaProperty +QmlSetPropertiesPrivate::property(const QByteArray &property) { + Q_Q(QmlSetProperties); + QList<QByteArray> path = property.split('.'); + + QObject *obj = this->object; + + for (int jj = 0; jj < path.count() - 1; ++jj) { + const QByteArray &pathName = path.at(jj); + QmlMetaProperty prop(obj, QLatin1String(pathName)); + QObject *objVal = QmlMetaType::toQObject(prop.read()); + if (!objVal) { + qmlInfo(q) << obj->metaObject()->className() + << "has no object property named" << pathName; + return QmlMetaProperty(); + } + obj = objVal; + } + + const QByteArray &name = path.last(); + QmlMetaProperty prop(obj, QLatin1String(name)); + if (!prop.isValid()) { + qmlInfo(q) << obj->metaObject()->className() + << "has no property named" << name; + return QmlMetaProperty(); + } else if (!prop.isWritable()) { + qmlInfo(q) << obj->metaObject()->className() + << name << "is not writable, and cannot be set."; + return QmlMetaProperty(); + } else { + return prop; + } +} + +QmlSetProperties::ActionList QmlSetProperties::actions() +{ + Q_D(QmlSetProperties); + + d->decode(); + ActionList list; - for (int ii = 0; ii < metaObject->count(); ++ii) { + for (int ii = 0; ii < d->properties.count(); ++ii) { + + QByteArray property = d->properties.at(ii).first; + QmlMetaProperty prop = d->property(property); - QByteArray name = metaObject->name(ii); - QVariant value = metaObject->value(ii); + if (prop.isValid()) { + Action a; + a.property = prop; + a.fromValue = a.property.read(); + a.toValue = d->properties.at(ii).second; - QmlSetPropertiesProxyObject *po = qobject_cast<QmlSetPropertiesProxyObject *>(qvariant_cast<QObject *>(value)); + list << a; + } + } - QmlMetaProperty prop(object, QLatin1String(name)); + for (int ii = 0; ii < d->expressions.count(); ++ii) { - if (po) { - QObject *objVal = QmlMetaType::toQObject(prop.read()); - if (!objVal) { - qmlInfo(this) << object->metaObject()->className() - << "has no object property named" << name; - continue; - } + QByteArray property = d->expressions.at(ii).first; + QmlMetaProperty prop = d->property(property); - list << doAction(po->fxMetaObject(), objVal); - } else if (!prop.isValid()) { - qmlInfo(this) << object->metaObject()->className() - << "has no property named" << name; - continue; - } else if (!prop.isWritable()) { - qmlInfo(this) << object->metaObject()->className() - << name << "is not writable, and cannot be set."; - continue; - } else { - //append action + if (prop.isValid()) { Action a; a.property = prop; - a.fromValue = prop.read(); - a.toValue = value; + a.fromValue = a.property.read(); + a.toValue = d->expressions.at(ii).second->value(); list << a; } + } return list; } -QmlSetProperties::ActionList QmlSetProperties::actions() -{ - Q_D(QmlSetProperties); - if (!d->obj) - return ActionList(); - - return doAction(d->mo, d->obj); -} +QML_DEFINE_CUSTOM_TYPE(QmlSetProperties,SetProperties,QmlSetPropertiesParser); QT_END_NAMESPACE #include "qmlsetproperties.moc" diff --git a/src/declarative/util/qmlsetproperties.h b/src/declarative/util/qmlsetproperties.h index f1f59ed..bd036c1 100644 --- a/src/declarative/util/qmlsetproperties.h +++ b/src/declarative/util/qmlsetproperties.h @@ -50,7 +50,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QmlSetPropertiesMetaObject; + class QmlSetPropertiesPrivate; class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation { @@ -58,20 +58,14 @@ class Q_DECLARATIVE_EXPORT QmlSetProperties : public QmlStateOperation Q_DECLARE_PRIVATE(QmlSetProperties); Q_PROPERTY(QObject *target READ object WRITE setObject); - public: QmlSetProperties(); - QmlSetProperties(QObject *parent); ~QmlSetProperties(); - QObject *object(); + QObject *object() const; void setObject(QObject *); virtual ActionList actions(); - -private: - ActionList doAction(QmlSetPropertiesMetaObject *, QObject *); - //QmlSetProperties::ActionList appendDotActions(const QVariant &, const QVariant &); }; QML_DECLARE_TYPE(QmlSetProperties); |