From b581d65a60c6b3a1d505b4cdfcbab1c81e48cee6 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 10 Sep 2009 10:00:09 +1000 Subject: typo --- doc/src/declarative/qmlformat.qdoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/declarative/qmlformat.qdoc b/doc/src/declarative/qmlformat.qdoc index 5013ee7..f16adca 100644 --- a/doc/src/declarative/qmlformat.qdoc +++ b/doc/src/declarative/qmlformat.qdoc @@ -91,8 +91,8 @@ The blue rectangle in the diagram represents a property binding. Associated wit binding is the QML context to which it belongs, the object property to which it is bound and a \e {scope object}. The scope object is usually, but not always, the object to which the bound property belongs. The context properties, context default objects and the scope object are all -involved when resolving a variable name in a binding. The following psuedo code describes the -alogithm used: +involved when resolving a variable name in a binding. The following pseudo code describes the +algorithm used: \table \row @@ -139,7 +139,7 @@ To the QML engine, a composite type is just another QML document. When a compos used the engine instantiates it just as it would any other document - by creating a new implicit QML context and the object tree described by the document. The diagram below shows the \c SquareImage composite type used from within another QML document. When instantiated, the -\c SquareImage object is created in its own QML context. Any property bindings sepecified in the +\c SquareImage object is created in its own QML context. Any property bindings specified in the \c SquareImage composite type document are associated with this context. Property bindings created in the outer document, however, are associated with its context, even those that are applied to the created \c SquareImage object. That is, the \c size, \c source, \c width and \c height property -- cgit v0.12 From 932f667eaad727854f6bb48d797874455ed13231 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 9 Sep 2009 20:38:13 +1000 Subject: Support URL resolution from within script blocks --- src/declarative/qml/qmlbinding.cpp | 4 ---- src/declarative/qml/qmlmetaproperty.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 39851ff..f9c9561 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -126,10 +126,6 @@ void QmlBinding::update() value = con(value.toString()); } - if (d->property.propertyType() == QVariant::Url && - (value.type() == QVariant::String || value.type() == QVariant::ByteArray) && !value.isNull()) - value.setValue(context()->resolvedUrl(QUrl(value.toString()))); - if (d->property.propertyType() == QVariant::Vector3D && value.type() == QVariant::String) { value = qVariantFromValue(QmlStringConverters::vector3DFromString(value.toString())); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index fdba79e..affb93b 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -874,6 +874,31 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value) } break; + case QVariant::Url: + { + QUrl u; + if (vt == QVariant::ByteArray) { + u = QUrl(QLatin1String(value.toByteArray())); + found = true; + } else if (QVariant::String) { + u = QUrl(value.toString()); + found = true; + } + + if (context && u.isRelative()) + u = context->baseUrl().resolved(u); + + if (found) { + void *a[1]; + a[0] = &u; + QMetaObject::metacall(object, + QMetaObject::WriteProperty, + coreIdx, a); + } + + } + break; + default: { -- cgit v0.12 From a250db23c96fc1ec47ea4d19d62a19cad7c50b46 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 10 Sep 2009 10:19:33 +1000 Subject: Report custom parse errors verbosely. --- src/declarative/qml/qmlcompiler.cpp | 11 ++--- src/declarative/qml/qmlcustomparser.cpp | 51 +++++++++++++++++++--- src/declarative/qml/qmlcustomparser_p.h | 19 +++++++- src/declarative/qml/qmlcustomparser_p_p.h | 9 ++-- src/declarative/util/qmllistmodel.cpp | 16 ++++--- src/declarative/util/qmlpropertychanges.cpp | 7 +-- .../qmlparser/customParserIdNotAllowed.errors.txt | 1 + .../qmlparser/customParserIdNotAllowed.qml | 5 +++ tests/auto/declarative/qmlparser/tst_qmlparser.cpp | 4 +- 9 files changed, 92 insertions(+), 31 deletions(-) create mode 100644 tests/auto/declarative/qmlparser/customParserIdNotAllowed.errors.txt create mode 100644 tests/auto/declarative/qmlparser/customParserIdNotAllowed.qml diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index b8e9d47..f02dad5 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -761,12 +761,13 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) // Compile custom parser parts if (isCustomParser && !customProps.isEmpty()) { - // ### Check for failure - bool ok = false; QmlCustomParser *cp = output->types.at(obj->type).type->customParser(); - obj->custom = cp->compile(customProps, &ok); - if(!ok) - COMPILE_EXCEPTION(obj, "Failure compiling custom type"); + cp->clearErrors(); + obj->custom = cp->compile(customProps); + foreach (QmlError err, cp->errors()) { + err.setUrl(output->url); + exceptions << err; + } } return true; diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp index b543978..dbcbeb1 100644 --- a/src/declarative/qml/qmlcustomparser.cpp +++ b/src/declarative/qml/qmlcustomparser.cpp @@ -70,7 +70,7 @@ using namespace QmlParser; */ /* - \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader, bool *ok) + \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader) Upon entry to this function, \a reader is positioned on a QXmlStreamReader::StartElement with the name specified when the @@ -80,7 +80,7 @@ using namespace QmlParser; EndElement matching the initial start element is reached, or until error. - On return, \c *ok indicates success. + Errors must be reported via the error() functions. The returned QByteArray contains data meaningful only to the custom parser; the type engine will pass this same data to @@ -109,6 +109,7 @@ QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root) { QmlCustomParserNode rootNode; rootNode.d->name = root->typeName; + rootNode.d->location = root->location.start; for(QHash::Iterator iter = root->properties.begin(); iter != root->properties.end(); @@ -128,6 +129,7 @@ QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) QmlCustomParserProperty prop; prop.d->name = p->name; prop.d->isList = (p->values.count() > 1); + prop.d->location = p->location.start; if (p->value) { QmlCustomParserNode node = fromObject(p->value); @@ -167,6 +169,7 @@ QmlCustomParserNode &QmlCustomParserNode::operator=(const QmlCustomParserNode &o { d->name = other.d->name; d->properties = other.d->properties; + d->location = other.d->location; return *this; } @@ -185,6 +188,11 @@ QList QmlCustomParserNode::properties() const return d->properties; } +QmlParser::Location QmlCustomParserNode::location() const +{ + return d->location; +} + QmlCustomParserProperty::QmlCustomParserProperty() : d(new QmlCustomParserPropertyPrivate) { @@ -201,6 +209,7 @@ QmlCustomParserProperty &QmlCustomParserProperty::operator=(const QmlCustomParse d->name = other.d->name; d->isList = other.d->isList; d->values = other.d->values; + d->location = other.d->location; return *this; } @@ -219,19 +228,49 @@ bool QmlCustomParserProperty::isList() const return d->isList; } +QmlParser::Location QmlCustomParserProperty::location() const +{ + return d->location; +} + QList QmlCustomParserProperty::assignedValues() const { return d->values; } -QByteArray QmlCustomParser::compile(const QList &, bool *ok) +void QmlCustomParser::clearErrors() { - Q_UNUSED(ok); - return QByteArray(); + exceptions.clear(); } -void QmlCustomParser::setCustomData(QObject *, const QByteArray &) +/*! + Reports an error in parsing \a prop, with the given \a description. + + An error is generated referring to the position of \a node in the source file. +*/ +void QmlCustomParser::error(const QmlCustomParserProperty& prop, const QString& description) +{ + QmlError error; + QString exceptionDescription; + error.setLine(prop.location().line); + error.setColumn(prop.location().column); + error.setDescription(description); + exceptions << error; +} + +/*! + Reports an error in parsing \a node, with the given \a description. + + An error is generated referring to the position of \a node in the source file. +*/ +void QmlCustomParser::error(const QmlCustomParserNode& node, const QString& description) { + QmlError error; + QString exceptionDescription; + error.setLine(node.location().line); + error.setColumn(node.location().column); + error.setDescription(description); + exceptions << error; } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h index 74bd15c..5be0680 100644 --- a/src/declarative/qml/qmlcustomparser_p.h +++ b/src/declarative/qml/qmlcustomparser_p.h @@ -57,6 +57,8 @@ #include #include #include +#include +#include QT_BEGIN_HEADER @@ -74,6 +76,7 @@ public: ~QmlCustomParserProperty(); QByteArray name() const; + QmlParser::Location location() const; bool isList() const; // Will be one of QmlParser::Variant, QmlCustomParserProperty or @@ -96,6 +99,7 @@ public: ~QmlCustomParserNode(); QByteArray name() const; + QmlParser::Location location() const; QList properties() const; @@ -109,8 +113,19 @@ class Q_DECLARATIVE_EXPORT QmlCustomParser public: virtual ~QmlCustomParser() {} - virtual QByteArray compile(const QList &, bool *ok); - virtual void setCustomData(QObject *, const QByteArray &); + void clearErrors(); + + virtual QByteArray compile(const QList &)=0; + virtual void setCustomData(QObject *, const QByteArray &)=0; + + QList errors() const { return exceptions; } + +protected: + void error(const QmlCustomParserProperty&, const QString& description); + void error(const QmlCustomParserNode&, const QString& description); + +private: + QList exceptions; }; #define QML_DEFINE_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, NAME, TYPE, CUSTOMTYPE) \ template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterCustomType(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, #NAME, #TYPE, new CUSTOMTYPE)); diff --git a/src/declarative/qml/qmlcustomparser_p_p.h b/src/declarative/qml/qmlcustomparser_p_p.h index 0011c3b..25023d3 100644 --- a/src/declarative/qml/qmlcustomparser_p_p.h +++ b/src/declarative/qml/qmlcustomparser_p_p.h @@ -55,20 +55,16 @@ #include #include "qmlcustomparser_p.h" +#include "qmlparser_p.h" QT_BEGIN_NAMESPACE -namespace QmlParser -{ - class Object; - class Property; -}; - class QmlCustomParserNodePrivate { public: QByteArray name; QList properties; + QmlParser::Location location; static QmlCustomParserNode fromObject(QmlParser::Object *); static QmlCustomParserProperty fromProperty(QmlParser::Property *); @@ -82,6 +78,7 @@ public: QByteArray name; bool isList; + QmlParser::Location location; QList values; }; diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index f988d81..19499a1 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -634,7 +634,7 @@ void QmlListModel::set(int index, const QString& property, const QVariant& value class QmlListModelParser : public QmlCustomParser { public: - QByteArray compile(const QList &, bool *ok); + QByteArray compile(const QList &); bool compileProperty(const QmlCustomParserProperty &prop, QList &instr, QByteArray &data); void setCustomData(QObject *, const QByteArray &); }; @@ -659,8 +659,14 @@ bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QL QList props = node.properties(); for(int jj = 0; jj < props.count(); ++jj) { const QmlCustomParserProperty &nodeProp = props.at(jj); - if(nodeProp.name() == "") + if (nodeProp.name() == "") { + error(nodeProp, QLatin1String("Cannot use default property in ListModel")); return false; + } + if (nodeProp.name() == "id") { + error(nodeProp, QLatin1String("Cannot use reserved \"id\" property in ListModel")); + return false; + } ListInstruction li; int ref = data.count(); @@ -706,21 +712,19 @@ bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QL return true; } -QByteArray QmlListModelParser::compile(const QList &customProps, bool *ok) +QByteArray QmlListModelParser::compile(const QList &customProps) { - *ok = true; QList instr; QByteArray data; for(int ii = 0; ii < customProps.count(); ++ii) { const QmlCustomParserProperty &prop = customProps.at(ii); if(prop.name() != "") { // isn't default property - *ok = false; + error(prop, QLatin1String("Cannot use default property")); return QByteArray(); } if(!compileProperty(prop, instr, data)) { - *ok = false; return QByteArray(); } } diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp index b5e204f..1fe1731 100644 --- a/src/declarative/util/qmlpropertychanges.cpp +++ b/src/declarative/util/qmlpropertychanges.cpp @@ -106,7 +106,7 @@ class QmlPropertyChangesParser : public QmlCustomParser public: void compileList(QList > &list, const QByteArray &pre, const QmlCustomParserProperty &prop); - virtual QByteArray compile(const QList &, bool *ok); + virtual QByteArray compile(const QList &); virtual void setCustomData(QObject *, const QByteArray &); }; @@ -137,11 +137,8 @@ QmlPropertyChangesParser::compileList(QList > &list, } QByteArray -QmlPropertyChangesParser::compile(const QList &props, - bool *ok) +QmlPropertyChangesParser::compile(const QList &props) { - *ok = true; - QList > data; for(int ii = 0; ii < props.count(); ++ii) compileList(data, QByteArray(), props.at(ii)); diff --git a/tests/auto/declarative/qmlparser/customParserIdNotAllowed.errors.txt b/tests/auto/declarative/qmlparser/customParserIdNotAllowed.errors.txt new file mode 100644 index 0000000..d28c0bd --- /dev/null +++ b/tests/auto/declarative/qmlparser/customParserIdNotAllowed.errors.txt @@ -0,0 +1 @@ +4:19:Cannot use reserved "id" property in ListModel diff --git a/tests/auto/declarative/qmlparser/customParserIdNotAllowed.qml b/tests/auto/declarative/qmlparser/customParserIdNotAllowed.qml new file mode 100644 index 0000000..e607768 --- /dev/null +++ b/tests/auto/declarative/qmlparser/customParserIdNotAllowed.qml @@ -0,0 +1,5 @@ +import Qt 4.6 +ListModel { + ListElement { a: 10 } + ListElement { id: Foo; a: 12 } +} diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp index e3735e7..25dfd27 100644 --- a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp +++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp @@ -159,6 +159,8 @@ void tst_qmlparser::errors_data() QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false; QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false; + + QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false; } void tst_qmlparser::errors() @@ -311,7 +313,7 @@ void tst_qmlparser::assignTypeExtremes() QCOMPARE(object->intProperty(), -0x77359400); } -// Tests that custom parser tyeps can be instantiated +// Tests that custom parser types can be instantiated void tst_qmlparser::customParserTypes() { QmlComponent component(&engine, TEST_FILE("customParserTypes.qml")); -- cgit v0.12