From c7a0cae7deb6e31c5b2e82c9a63ebe0a167fed09 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 11:17:15 +1000 Subject: Improve error handling consistency --- src/declarative/qml/qml.pri | 6 +- src/declarative/qml/qmlcompiler.cpp | 33 +++-- src/declarative/qml/qmlcompiler_p.h | 5 +- src/declarative/qml/qmlcomponent.cpp | 24 ++-- src/declarative/qml/qmlcomponent.h | 5 +- src/declarative/qml/qmlcomponent_p.h | 3 +- src/declarative/qml/qmlcompositetypemanager.cpp | 23 +-- src/declarative/qml/qmlcompositetypemanager_p.h | 4 +- src/declarative/qml/qmldom.cpp | 18 +-- src/declarative/qml/qmldom.h | 2 + src/declarative/qml/qmldom_p.h | 2 +- src/declarative/qml/qmlerror.cpp | 180 ++++++++++++++++++++++++ src/declarative/qml/qmlerror.h | 82 +++++++++++ src/declarative/qml/qmlparser.cpp | 8 +- src/declarative/qml/qmlparser_p.h | 3 + src/declarative/qml/qmlscriptparser.cpp | 104 +++++++------- src/declarative/qml/qmlscriptparser_p.h | 11 +- src/declarative/qml/qmlvme.cpp | 24 ++-- src/declarative/qml/qmlvme_p.h | 5 +- src/declarative/util/qfxview.cpp | 79 ++++++++++- src/declarative/util/qfxview.h | 3 +- tools/qmlviewer/qmlviewer.cpp | 8 ++ 22 files changed, 501 insertions(+), 131 deletions(-) create mode 100644 src/declarative/qml/qmlerror.cpp create mode 100644 src/declarative/qml/qmlerror.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 9067039..69a1461 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -22,7 +22,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlclassfactory.cpp \ qml/qmlparserstatus.cpp \ qml/qmlcompositetypemanager.cpp \ - qml/qmlinfo.cpp + qml/qmlinfo.cpp \ + qml/qmlerror.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -58,7 +59,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcontext_p.h \ qml/qmlcompositetypemanager_p.h \ qml/qmllist.h \ - qml/qmldeclarativedata_p.h + qml/qmldeclarativedata_p.h \ + qml/qmlerror.h # for qtscript debugger QT += scripttools diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index c9bdfec..37d7fa1 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -147,7 +147,7 @@ int QmlCompiledData::indexForInt(int *data, int count) } QmlCompiler::QmlCompiler() -: exceptionLine(-1), output(0) +: exceptionLine(-1), exceptionColumn(-1), output(0) { } @@ -156,14 +156,19 @@ bool QmlCompiler::isError() const return exceptionLine != -1; } -qint64 QmlCompiler::errorLine() const +QList QmlCompiler::errors() const { - return exceptionLine; -} + QList rv; + + if(isError()) { + QmlError error; + error.setDescription(exceptionDescription); + error.setLine(exceptionLine); + error.setColumn(exceptionColumn); + rv << error; + } -QString QmlCompiler::errorDescription() const -{ - return exceptionDescription; + return rv; } bool QmlCompiler::isValidId(const QString &val) @@ -437,9 +442,19 @@ void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory) cc->bytecode.clear(); } +#define COMPILE_EXCEPTION2(token, desc) \ + { \ + exceptionLine = token->line; \ + exceptionColumn = token->column; \ + QDebug d(&exceptionDescription); \ + d << desc; \ + return false; \ + } + #define COMPILE_EXCEPTION(desc) \ { \ exceptionLine = obj->line; \ + exceptionColumn = obj->column; \ QDebug d(&exceptionDescription); \ d << desc; \ return false; \ @@ -1215,10 +1230,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, //### we are restricted to a rather generic message here. If we can find a way to move // the exception into generateStoreInstruction we could potentially have better messages. // (the problem is that both compile and run exceptions can be generated, though) - COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name()); + COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name()); doassign = false; } else if (r == ReadOnly) { - COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name()); + COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name()); } else { doassign = true; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 9a0ce1c..cc1a9e9 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include class QStringList; @@ -115,8 +116,7 @@ public: bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledComponent *); bool isError() const; - qint64 errorLine() const; - QString errorDescription() const; + QList errors() const; static bool isValidId(const QString &); static bool isBinding(const QString &); @@ -176,6 +176,7 @@ private: QSet ids; qint64 exceptionLine; + qint64 exceptionColumn; QString exceptionDescription; QmlCompiledData *output; }; diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index c316f03..3b4d7b3 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -137,9 +137,7 @@ void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data) if (!c) { Q_ASSERT(data->status == QmlCompositeTypeData::Error); - errorDescription = data->errorDescription; - qWarning().nospace() << "QmlComponent: " - << data->errorDescription.toLatin1().constData(); + errors = data->errors; } else { @@ -194,7 +192,7 @@ QmlComponent::Status QmlComponent::status() const return Loading; else if (d->engine && d->cc) return Ready; - else if (!d->errorDescription.isEmpty()) + else if (!d->errors.isEmpty()) return Error; else return Null; @@ -353,13 +351,13 @@ void QmlComponent::loadUrl(const QUrl &url) emit statusChanged(status()); } -QString QmlComponent::errorDescription() const +QList QmlComponent::errors() const { Q_D(const QmlComponent); if (isError()) - return d->errorDescription; + return d->errors; else - return QString(); + return QList(); } /*! @@ -448,7 +446,7 @@ QObject *QmlComponent::beginCreate(QmlContext *context) } if (!isReady()) { - qWarning("QmlComponent: Cannot create un-ready component"); + qWarning("QmlComponent: Component is not ready"); return 0; } @@ -466,15 +464,9 @@ QObject *QmlComponent::beginCreate(QmlContext *context) QmlVME vme; QObject *rv = vme.run(ctxt, d->cc, d->start, d->count); - if (vme.isError()) { - qWarning().nospace() -#ifdef QML_VERBOSEERRORS_ENABLED - << "QmlComponent: " -#endif - << vme.errorDescription().toLatin1().constData() << " @" - << d->url.toString().toLatin1().constData() << ":" << vme.errorLine(); - } + if (vme.isError()) + d->errors = vme.errors(); ctxt->deactivate(); diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h index 0493c1f..90f7467 100644 --- a/src/declarative/qml/qmlcomponent.h +++ b/src/declarative/qml/qmlcomponent.h @@ -46,7 +46,7 @@ #include #include #include - +#include QT_BEGIN_HEADER @@ -77,7 +77,8 @@ public: bool isReady() const; bool isError() const; bool isLoading() const; - QString errorDescription() const; + + QList errors() const; QUrl url() const; diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index bb5f7bb..0507958 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -47,6 +47,7 @@ #include #include "private/qobject_p.h" #include "private/qmlcompositetypemanager_p.h" +#include #include "qmlcomponent.h" class QmlComponent; class QmlEngine; @@ -68,7 +69,7 @@ public: void fromTypeData(QmlCompositeTypeData *data); - QString errorDescription; + QList errors; QUrl url; int start; diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index 7f2cc58..fbe40bf 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -105,10 +105,9 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine) QmlCompiler compiler; if (!compiler.compile(engine, this, compiledComponent)) { status = Error; - errorDescription = compiler.errorDescription() + - QLatin1String("@") + - url + QLatin1String(":") + - QString::number(compiler.errorLine()); + errors = compiler.errors(); + for(int ii = 0; ii < errors.count(); ++ii) + errors[ii].setUrl(url); compiledComponent->release(); compiledComponent = 0; } @@ -188,7 +187,10 @@ void QmlCompositeTypeManager::replyFinished() reply->url().toString(); unit->status = QmlCompositeTypeData::Error; - unit->errorDescription = errorDescription; + // ### FIXME + QmlError error; + error.setDescription(errorDescription); + unit->errors << error; doComplete(unit); } else { @@ -215,7 +217,10 @@ void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit) // ### - Fill in error errorDescription = QLatin1String("File error for URL ") + url.toString(); unit->status = QmlCompositeTypeData::Error; - unit->errorDescription = errorDescription; + // ### FIXME + QmlError error; + error.setDescription(errorDescription); + unit->errors << error; doComplete(unit); } @@ -234,7 +239,7 @@ void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit, if (!unit->data.parse(data, url)) { unit->status = QmlCompositeTypeData::Error; - unit->errorDescription = unit->data.errorDescription(); + unit->errors << unit->data.errors(); doComplete(unit); } else { @@ -273,7 +278,7 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit) if (u->status == QmlCompositeTypeData::Error) { unit->status = QmlCompositeTypeData::Error; - unit->errorDescription = u->errorDescription; + unit->errors = u->errors; doComplete(unit); return; } else if (u->status == QmlCompositeTypeData::Waiting) { @@ -334,7 +339,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) case QmlCompositeTypeData::Invalid: case QmlCompositeTypeData::Error: unit->status = QmlCompositeTypeData::Error; - unit->errorDescription = urlUnit->errorDescription; + unit->errors = urlUnit->errors; doComplete(unit); return; diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h index bc86fcf..e4028d5 100644 --- a/src/declarative/qml/qmlcompositetypemanager_p.h +++ b/src/declarative/qml/qmlcompositetypemanager_p.h @@ -45,6 +45,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -65,7 +66,8 @@ struct QmlCompositeTypeData : public QmlRefCount Waiting }; Status status; - QString errorDescription; + + QList errors; QString url; QList dependants; diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index cf0a2fb..239aa7b 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -152,11 +152,11 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data) { Q_UNUSED(engine); - d->error = QString(); + d->errors.clear(); QmlScriptParser parser; if (!parser.parse(data)) { - d->error = parser.errorDescription(); + d->errors = parser.errors(); return false; } @@ -166,11 +166,13 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data) QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, QUrl());; if(td->status == QmlCompositeTypeData::Error) { - d->error = td->errorDescription; + d->errors = td->errors; td->release(); return false; } else if(td->status == QmlCompositeTypeData::Waiting) { - d->error = QLatin1String("QmlDomDocument supports local types only"); + QmlError error; + error.setDescription(QLatin1String("QmlDomDocument supports local types only")); + d->errors << error; td->release(); return false; } @@ -178,7 +180,7 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data) compiler.compile(engine, td, &component); if (compiler.isError()) { - d->error = compiler.errorDescription(); + d->errors = compiler.errors(); td->release(); return false; } @@ -194,14 +196,14 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data) /*! - Returns the last load error. The load error will be reset after a + Returns the last load errors. The load errors will be reset after a successful call to load(). \sa load() */ -QString QmlDomDocument::loadError() const +QList QmlDomDocument::errors() const { - return d->error; + return d->errors; } /*! diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h index 47a89d9..74ed27c 100644 --- a/src/declarative/qml/qmldom.h +++ b/src/declarative/qml/qmldom.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -71,6 +72,7 @@ public: int version() const; + QList errors() const; QString loadError() const; bool load(QmlEngine *, const QByteArray &); QByteArray save() const; diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h index 8ea56bf..4c3ca44 100644 --- a/src/declarative/qml/qmldom_p.h +++ b/src/declarative/qml/qmldom_p.h @@ -57,7 +57,7 @@ public: QmlDomDocumentPrivate(const QmlDomDocumentPrivate &); ~QmlDomDocumentPrivate(); - QString error; + QList errors; QmlParser::Object *root; }; diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp new file mode 100644 index 0000000..66c834f --- /dev/null +++ b/src/declarative/qml/qmlerror.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlerror.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlErrorPrivate +{ +public: + QmlErrorPrivate(); + + QUrl url; + QString description; + int line; + int column; +}; + +QmlErrorPrivate::QmlErrorPrivate() +: line(-1), column(-1) +{ +} + +QmlError::QmlError() +: d(new QmlErrorPrivate) +{ +} + +QmlError::QmlError(const QmlError &other) +: d(new QmlErrorPrivate) +{ + *this = other; +} + +QmlError &QmlError::operator=(const QmlError &other) +{ + d->url = other.d->url; + d->description = other.d->description; + d->line = other.d->line; + d->column = other.d->column; + return *this; +} + +QmlError::~QmlError() +{ + delete d; d = 0; +} + +QUrl QmlError::url() const +{ + return d->url; +} + +void QmlError::setUrl(const QUrl &url) +{ + d->url = url; +} + +QString QmlError::description() const +{ + return d->description; +} + +void QmlError::setDescription(const QString &description) +{ + d->description = description; +} + +int QmlError::line() const +{ + return d->line; +} + +void QmlError::setLine(int line) +{ + d->line = line; +} + +int QmlError::column() const +{ + return d->column; +} + +void QmlError::setColumn(int column) +{ + d->column = column; +} + +QDebug operator<<(QDebug debug, const QmlError &error) +{ + QUrl url = error.url(); + + QString output; + + output = url.toString() + QLatin1String(":") + + QString::number(error.line()); + + if(error.column() != -1) + output += QLatin1String(":") + QString::number(error.column()); + + output += QLatin1String(": ") + error.description(); + + debug << qPrintable(output) << "\n"; + + if (error.line() > 0 && error.column() > 0 && + url.scheme() == QLatin1String("file")) { + QString file = url.toLocalFile(); + QFile f(file); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data = f.readAll(); + QTextStream stream(data, QIODevice::ReadOnly); + const QString code = stream.readAll(); + const QStringList lines = code.split(QLatin1Char('\n')); + + if (lines.count() >= error.line()) { + const QString &line = lines.at(error.line() - 1); + debug << qPrintable(line) << "\n"; + + int column = qMax(0, error.column() - 1); + column = qMin(column, line.length()); + + QByteArray ind; + ind.reserve(column); + for (int i = 0; i < column; ++i) { + const QChar ch = line.at(i); + if (ch.isSpace()) + ind.append(ch.unicode()); + else + ind.append(' '); + } + ind.append('^'); + debug << ind.constData(); + } + } + } + return debug; +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h new file mode 100644 index 0000000..57d2f8f --- /dev/null +++ b/src/declarative/qml/qmlerror.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLERROR_H +#define QMLERROR_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDebug; +class QmlErrorPrivate; +class Q_DECLARATIVE_EXPORT QmlError +{ +public: + QmlError(); + QmlError(const QmlError &); + QmlError &operator=(const QmlError &); + ~QmlError(); + + QUrl url() const; + void setUrl(const QUrl &); + QString description() const; + void setDescription(const QString &); + int line() const; + void setLine(int); + int column() const; + void setColumn(int); +private: + QmlErrorPrivate *d; +}; + +QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLERROR_H diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index ecb6f0b..87c8434 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE using namespace QmlParser; QmlParser::Object::Object() -: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1), +: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1), column(-1), dynamicPropertiesProperty(0), dynamicSignalsProperty(0) { } @@ -127,12 +127,12 @@ QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o) } QmlParser::Property::Property() -: type(0), index(-1), value(0), isDefault(true), line(-1) +: type(0), index(-1), value(0), isDefault(true), line(-1), column(-1) { } QmlParser::Property::Property(const QByteArray &n) -: type(0), index(-1), value(0), name(n), isDefault(false), line(-1) +: type(0), index(-1), value(0), name(n), isDefault(false), line(-1), column(-1) { } @@ -161,7 +161,7 @@ void QmlParser::Property::addValue(Value *v) } QmlParser::Value::Value() -: type(Unknown), object(0), line(-1) +: type(Unknown), object(0), line(-1), column(-1) { } diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index e29cdbf..17b367d6 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -103,6 +103,7 @@ namespace QmlParser QHash properties; qint64 line; + qint64 column; struct DynamicProperty { DynamicProperty(); @@ -167,6 +168,7 @@ namespace QmlParser Object *object; qint64 line; + qint64 column; }; class Property : public QmlRefCount @@ -197,6 +199,7 @@ namespace QmlParser bool isDefault; qint64 line; + qint64 column; }; } diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 8039b5c..618eb2e 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -65,10 +65,12 @@ protected: Object *defineObjectBinding(int line, AST::UiQualifiedId *propertyName, const QString &objectType, + AST::SourceLocation typeLocation, AST::UiObjectInitializer *initializer = 0); Object *defineObjectBinding_helper(int line, AST::UiQualifiedId *propertyName, const QString &objectType, + AST::SourceLocation typeLocation, AST::UiObjectInitializer *initializer = 0); QString getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr); void defineProperty(const QString &propertyName, int line, const QString &primitive); @@ -194,11 +196,17 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const Object *ProcessAST::defineObjectBinding_helper(int line, AST::UiQualifiedId *propertyName, const QString &objectType, + AST::SourceLocation typeLocation, AST::UiObjectInitializer *initializer) { bool isType = !objectType.isEmpty() && objectType.at(0).isUpper() && !objectType.contains(QLatin1Char('.')); + if (!isType) { - qWarning() << "bad name for a class"; // ### FIXME + QmlError error; + error.setDescription("Expected type name"); + error.setLine(typeLocation.startLine); + error.setColumn(typeLocation.startColumn); + _parser->_errors << error; return false; } @@ -235,7 +243,7 @@ Object *ProcessAST::defineObjectBinding_helper(int line, if (!_parser->scriptFile().isEmpty()) { _stateStack.pushObject(obj); - Object *scriptObject= defineObjectBinding(line, 0, QLatin1String("Script")); + Object *scriptObject= defineObjectBinding(line, 0, QLatin1String("Script"), AST::SourceLocation()); _stateStack.pushObject(scriptObject); defineProperty(QLatin1String("src"), line, _parser->scriptFile()); _stateStack.pop(); // scriptObject @@ -264,11 +272,12 @@ Object *ProcessAST::defineObjectBinding_helper(int line, Object *ProcessAST::defineObjectBinding(int line, AST::UiQualifiedId *qualifiedId, const QString &objectType, + AST::SourceLocation typeLocation, AST::UiObjectInitializer *initializer) { if (objectType == QLatin1String("Connection")) { - Object *obj = defineObjectBinding_helper(line, 0, QLatin1String("Connection")); + Object *obj = defineObjectBinding_helper(line, 0, objectType, typeLocation); _stateStack.pushObject(obj); @@ -297,7 +306,7 @@ Object *ProcessAST::defineObjectBinding(int line, return obj; } - return defineObjectBinding_helper(line, qualifiedId, objectType, initializer); + return defineObjectBinding_helper(line, qualifiedId, objectType, typeLocation, initializer); } void ProcessAST::defineProperty(const QString &propertyName, int line, const QString &primitive) @@ -372,7 +381,11 @@ bool ProcessAST::visit(AST::UiPublicMember *node) } if(!typeFound) { - qWarning() << "Unknown property type" << memberType; // ### FIXME + QmlError error; + error.setDescription("Expected property type"); + error.setLine(node->typeToken.startLine); + error.setColumn(node->typeToken.startColumn); + _parser->_errors << error; return false; } @@ -402,6 +415,7 @@ bool ProcessAST::visit(AST::UiObjectDefinition *node) defineObjectBinding(node->identifierToken.startLine, 0, node->name->asString(), + node->identifierToken, node->initializer); return false; @@ -414,6 +428,7 @@ bool ProcessAST::visit(AST::UiObjectBinding *node) defineObjectBinding(node->identifierToken.startLine, node->qualifiedId, node->name->asString(), + node->identifierToken, node->initializer); return false; @@ -476,7 +491,8 @@ bool ProcessAST::visit(AST::UiScriptBinding *node) Value *v = new Value; v->primitive = primitive; - v->line = node->colonToken.startLine; + v->line = node->statement->firstSourceLocation().startLine; + v->column = node->statement->firstSourceLocation().startColumn; prop->addValue(v); while (propertyCount--) @@ -535,7 +551,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) QmlScriptParser::QmlScriptParser() - : root(0), _errorLine(-1) +: root(0) { } @@ -556,8 +572,11 @@ bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url) return true; } - _error = xmlParser.errorDescription(); - _errorLine = 0; // ### FIXME + QmlError error; + error.setUrl(url); + error.setDescription(xmlParser.errorDescription()); + _errors << error; + return false; } @@ -576,61 +595,34 @@ bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url) lexer.setCode(code, /*line = */ 1); driver.setLexer(&lexer); - if (! parser.parse(&driver)) { - _error = parser.errorMessage(); - _errorLine = parser.errorLineNumber(); - - const QStringList lines = code.split(QLatin1Char('\n')); + if (! parser.parse(&driver) || !_errors.isEmpty()) { + // Extract errors from the parser foreach (const JavaScriptParser::DiagnosticMessage &m, parser.diagnosticMessages()) { if (m.isWarning()) continue; - qWarning().nospace() << qPrintable(fileName) << ":" - << m.line << ":" - << m.column << ": " - << "error: " - << qPrintable(m.message); - - const QString textLine = lines.at(m.line - 1); - - qWarning() << qPrintable(textLine); + QmlError error; + error.setUrl(url); + error.setDescription(m.message); + error.setLine(m.line); + error.setColumn(m.column); + _errors << error; - int column = qMax(0, m.column - 1); - column = qMin(column, textLine.length()); // paranoia check - - QByteArray ind; - ind.reserve(column); - - for (int i = 0; i < column; ++i) { - const QChar ch = textLine.at(i); - if (ch.isSpace()) - ind.append(ch.unicode()); - else - ind.append(' '); - } - ind.append('^'); - qWarning() << ind.constData(); } - - return false; } - ProcessAST process(this); - process(code, parser.ast()); + if (_errors.isEmpty()) { + ProcessAST process(this); + process(code, parser.ast()); - return true; -} - -QString QmlScriptParser::errorDescription() const -{ - return _error; -} + // Set the url for process errors + for(int ii = 0; ii < _errors.count(); ++ii) + _errors[ii].setUrl(url); + } -int QmlScriptParser::errorLine() const -{ - return _errorLine; + return _errors.isEmpty(); } QMap QmlScriptParser::nameSpacePaths() const @@ -648,6 +640,11 @@ Object *QmlScriptParser::tree() const return root; } +QList QmlScriptParser::errors() const +{ + return _errors; +} + void QmlScriptParser::clear() { if (root) { @@ -656,9 +653,8 @@ void QmlScriptParser::clear() } _nameSpacePaths.clear(); _typeNames.clear(); - _error.clear(); + _errors.clear(); _scriptFile.clear(); - _errorLine = 0; } int QmlScriptParser::findOrCreateTypeId(const QString &name) diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h index 0d89268..4155bba 100644 --- a/src/declarative/qml/qmlscriptparser_p.h +++ b/src/declarative/qml/qmlscriptparser_p.h @@ -3,6 +3,7 @@ #include #include +#include #include QT_BEGIN_HEADER @@ -23,8 +24,6 @@ public: ~QmlScriptParser(); bool parse(const QByteArray &data, const QUrl &url = QUrl()); - QString errorDescription() const; - int errorLine() const; QMap nameSpacePaths() const; QStringList types() const; @@ -33,6 +32,8 @@ public: void clear(); + QList errors() const; + // ### private: int findOrCreateTypeId(const QString &name); void setTree(QmlParser::Object *tree); @@ -42,12 +43,12 @@ public: void addNamespacePath(const QString &path); -private: +// ### private: + QList _errors; + QMap _nameSpacePaths; QmlParser::Object *root; QStringList _typeNames; - QString _error; - int _errorLine; QString _scriptFile; }; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index e6235e4..a3bfd62 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -176,9 +176,14 @@ QmlVME::QmlVME() #define VME_EXCEPTION(desc) \ { \ - exceptionLine = instr.line; \ - QDebug d(&exceptionDescription); \ - d << desc; \ + QString str; \ + QDebug d(&str); \ + d << desc; \ + QmlError error; \ + error.setDescription(str); \ + error.setLine(instr.line); \ + error.setUrl(comp->url); \ + vmeErrors << error; \ break; \ } @@ -224,6 +229,8 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in QStack pushedProperties; QObject **savedObjects = 0; + vmeErrors.clear(); + if (start == -1) start = 0; if (count == -1) count = comp->bytecode.count(); @@ -1072,17 +1079,12 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in bool QmlVME::isError() const { - return exceptionLine != -1; -} - -qint64 QmlVME::errorLine() const -{ - return exceptionLine; + return !vmeErrors.isEmpty(); } -QString QmlVME::errorDescription() const +QList QmlVME::errors() const { - return exceptionDescription; + return vmeErrors; } void QmlVME::runStoreInstruction(QStack &stack, diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h index 2a3be06..86cd040 100644 --- a/src/declarative/qml/qmlvme_p.h +++ b/src/declarative/qml/qmlvme_p.h @@ -44,6 +44,7 @@ #include #include +#include class QObject; QT_BEGIN_NAMESPACE @@ -60,13 +61,13 @@ public: QObject *run(QmlContext *, QmlCompiledComponent *, int start = -1, int end = -1); bool isError() const; - qint64 errorLine() const; - QString errorDescription() const; + QList errors() const; private: void runStoreInstruction(QStack &stack, QmlInstruction &, QmlCompiledData *); + QList vmeErrors; qint64 exceptionLine; QString exceptionDescription; }; diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp index cac73a0..f71b87e 100644 --- a/src/declarative/util/qfxview.cpp +++ b/src/declarative/util/qfxview.cpp @@ -233,8 +233,6 @@ QmlContext* QFxView::rootContext() */ void QFxView::execute() { - rootContext()->activate(); - if (d->qml.isEmpty()) { d->component = new QmlComponent(&d->engine, d->source, this); } else { @@ -249,6 +247,45 @@ void QFxView::execute() } /*! + \internal +*/ +void QFxView::printErrorLine(const QmlError &error) +{ + QUrl url = error.url(); + if (error.line() > 0 && error.column() > 0 && + url.scheme() == QLatin1String("file")) { + QString file = url.toLocalFile(); + QFile f(file); + if (f.open(QIODevice::ReadOnly)) { + QByteArray data = f.readAll(); + QTextStream stream(data, QIODevice::ReadOnly); + const QString code = stream.readAll(); + const QStringList lines = code.split(QLatin1Char('\n')); + + if (lines.count() >= error.line()) { + const QString &line = lines.at(error.line() - 1); + qWarning() << qPrintable(line); + + int column = qMax(0, error.column() - 1); + column = qMin(column, line.length()); + + QByteArray ind; + ind.reserve(column); + for (int i = 0; i < column; ++i) { + const QChar ch = line.at(i); + if (ch.isSpace()) + ind.append(ch.unicode()); + else + ind.append(' '); + } + ind.append('^'); + qWarning() << ind.constData(); + } + } + } +} + +/*! \internal */ void QFxView::continueExecute() @@ -260,8 +297,26 @@ void QFxView::continueExecute() return; } + if(d->component->isError()) { + QList errors = d->component->errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + + return; + } + QObject *obj = d->component->create(); - rootContext()->deactivate(); + + if(d->component->isError()) { + QList errors = d->component->errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + + return; + } + if (obj) { if (QFxItem *item = qobject_cast(obj)) { item->QSimpleCanvasItem::setParent(QSimpleCanvas::root()); @@ -330,7 +385,25 @@ QFxItem* QFxView::addItem(const QString &qml, QFxItem* parent) return 0; QmlComponent component(&d->engine, qml.toUtf8(), QUrl()); + if(d->component->isError()) { + QList errors = d->component->errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + + return 0; + } + QObject *obj = component.create(); + if(d->component->isError()) { + QList errors = d->component->errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + + return 0; + } + if (obj){ QFxItem *item = static_cast(obj); if (!parent) diff --git a/src/declarative/util/qfxview.h b/src/declarative/util/qfxview.h index d2cacf4..f575f27 100644 --- a/src/declarative/util/qfxview.h +++ b/src/declarative/util/qfxview.h @@ -57,7 +57,7 @@ QT_MODULE(Declarative) class QFxItem; class QmlEngine; class QmlContext; -class Canvas; +class QmlError; class QFxViewPrivate; class Q_DECLARATIVE_EXPORT QFxView : public QSimpleCanvas @@ -84,6 +84,7 @@ public: void dumpRoot(); + static void printErrorLine(const QmlError &); Q_SIGNALS: void sceneResized(QSize size); diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp index 3c52cfe..00cb7f1 100644 --- a/tools/qmlviewer/qmlviewer.cpp +++ b/tools/qmlviewer/qmlviewer.cpp @@ -85,6 +85,14 @@ void QmlViewer::openQml(const QString& fileName) QmlComponent comp(canvas->engine()); comp.setData(data, QUrl()); QObject *dummyData = comp.create(); + + if(comp.isError()) { + QList errors = comp.errors(); + foreach (const QmlError &error, errors) { + qWarning() << error; + } + } + if (dummyData) { qWarning() << "Loaded dummy data:" << dir.filePath(qml); qml.truncate(qml.length()-4); -- cgit v0.12 From f7573945387671cafaff14924905859e296b47f7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 12:46:41 +1000 Subject: QmlError doc --- src/declarative/qml/qmlcomponent.cpp | 4 +++ src/declarative/qml/qmlerror.cpp | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 3b4d7b3..66440f5 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -351,6 +351,10 @@ void QmlComponent::loadUrl(const QUrl &url) emit statusChanged(status()); } +/*! + Return the list of errors that occured during the last compile or create + operation. An empty list is returned if isError() is not set. +*/ QList QmlComponent::errors() const { Q_D(const QmlComponent); diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp index 66c834f..2ed3500 100644 --- a/src/declarative/qml/qmlerror.cpp +++ b/src/declarative/qml/qmlerror.cpp @@ -46,6 +46,10 @@ QT_BEGIN_NAMESPACE +/*! + \class QmlError + \brief The QmlError class encapsulates a QML error +*/ class QmlErrorPrivate { public: @@ -62,17 +66,26 @@ QmlErrorPrivate::QmlErrorPrivate() { } +/*! + Create an empty error object. +*/ QmlError::QmlError() : d(new QmlErrorPrivate) { } +/*! + Create a copy of \a other. +*/ QmlError::QmlError(const QmlError &other) : d(new QmlErrorPrivate) { *this = other; } +/*! + Assign \a other to this error object. +*/ QmlError &QmlError::operator=(const QmlError &other) { d->url = other.d->url; @@ -82,51 +95,85 @@ QmlError &QmlError::operator=(const QmlError &other) return *this; } +/*! + \internal +*/ QmlError::~QmlError() { delete d; d = 0; } +/*! + Return the url for the file that caused this error. +*/ QUrl QmlError::url() const { return d->url; } +/*! + Set the \a url for the file that caused this error. +*/ void QmlError::setUrl(const QUrl &url) { d->url = url; } +/*! + Return the error description. +*/ QString QmlError::description() const { return d->description; } +/*! + Set the error \a description. +*/ void QmlError::setDescription(const QString &description) { d->description = description; } +/*! + Return the error line number. +*/ int QmlError::line() const { return d->line; } +/*! + Set the error \a line number. +*/ void QmlError::setLine(int line) { d->line = line; } +/*! + Return the error column number. +*/ int QmlError::column() const { return d->column; } +/*! + Set the error \a column number. +*/ void QmlError::setColumn(int column) { d->column = column; } +/*! + \relates QmlError + \fn QDebug operator<<(QDebug debug, const QmlError &error) + + Output a human readable version of \a error to \a debug. +*/ + QDebug operator<<(QDebug debug, const QmlError &error) { QUrl url = error.url(); -- cgit v0.12 From caa1832f8dd6012ed3d44d7b822c500485ffb5ec Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 12:49:26 +1000 Subject: Mark DOM API as internal for now --- src/declarative/qml/qmldom.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index 3942375..08755b1 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -70,6 +70,7 @@ QmlDomDocumentPrivate::~QmlDomDocumentPrivate() /*! \class QmlDomDocument + \internal \brief The QmlDomDocument class represents the root of a QML document A QML document is a self-contained snippet of QML, usually contained in a @@ -251,6 +252,7 @@ QmlDomPropertyPrivate::~QmlDomPropertyPrivate() /*! \class QmlDomProperty + \internal \brief The QmlDomProperty class represents one property assignment in the QML DOM tree @@ -452,6 +454,7 @@ QmlDomObjectPrivate::properties(QmlParser::Property *property) const /*! \class QmlDomObject + \internal \brief The QmlDomObject class represents an object instantiation. Each object instantiated in a QML file has a corresponding QmlDomObject @@ -736,6 +739,7 @@ QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate() /*! \class QmlDomValueLiteral + \internal \brief The QmlDomValueLiteral class represents a literal value. A literal value is a simple value, written inline with the QML. In the @@ -808,6 +812,7 @@ void QmlDomValueLiteral::setLiteral(const QString &value) /*! \class QmlDomValueBinding + \internal \brief The QmlDomValueBinding class represents a property binding. A property binding is an ECMAScript expression assigned to a property. In @@ -877,6 +882,7 @@ void QmlDomValueBinding::setBinding(const QString &expression) /*! \class QmlDomValueValueSource + \internal \brief The QmlDomValueValueSource class represents a value source assignment value. In QML, value sources are special value generating types that may be @@ -985,6 +991,7 @@ QmlDomValuePrivate::~QmlDomValuePrivate() /*! \class QmlDomValue + \internal \brief The QmlDomValue class represents a generic Qml value. QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In @@ -1236,6 +1243,7 @@ QmlDomList QmlDomValue::toList() const /*! \class QmlDomList + \internal \brief The QmlDomList class represents a list of values assigned to a QML property. Lists of values can be assigned to properties. For example, the following @@ -1325,6 +1333,7 @@ void QmlDomList::setValues(const QList &values) /*! \class QmlDomComponent + \internal \brief The QmlDomComponent class represents sub-component within a QML document. Sub-components are QmlComponents defined within a QML document. The -- cgit v0.12 From ca737861c5b6459a3f5f33cafbbe371da5c113c4 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 5 May 2009 13:17:20 +1000 Subject: Minehunt switched to KDE smiley faces Minehunt example now meets minimum aesthetic requirements. --- examples/declarative/minehunt/minehunt.qml | 6 +++--- examples/declarative/minehunt/pics/face-sad.png | Bin 0 -> 14844 bytes examples/declarative/minehunt/pics/face-smile-big.png | Bin 0 -> 13810 bytes examples/declarative/minehunt/pics/face-smile.png | Bin 0 -> 15408 bytes examples/declarative/minehunt/pics/frown.png | Bin 1036 -> 0 bytes examples/declarative/minehunt/pics/glee.png | Bin 1082 -> 0 bytes examples/declarative/minehunt/pics/smile.png | Bin 1028 -> 0 bytes 7 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 examples/declarative/minehunt/pics/face-sad.png create mode 100644 examples/declarative/minehunt/pics/face-smile-big.png create mode 100644 examples/declarative/minehunt/pics/face-smile.png delete mode 100644 examples/declarative/minehunt/pics/frown.png delete mode 100644 examples/declarative/minehunt/pics/glee.png delete mode 100644 examples/declarative/minehunt/pics/smile.png diff --git a/examples/declarative/minehunt/minehunt.qml b/examples/declarative/minehunt/minehunt.qml index 58397b0..bf31c3d 100644 --- a/examples/declarative/minehunt/minehunt.qml +++ b/examples/declarative/minehunt/minehunt.qml @@ -148,9 +148,9 @@ Item { text: numFlags } Image { - x: 240 - y: 0 - source: if(isPlaying==true){'pics/smile.png'}else{if(hasWon==true){'pics/glee.png'}else{'pics/frown.png'}} + x: 280 + y: 10 + source: if(isPlaying==true){'pics/face-smile.png'}else{if(hasWon==true){'pics/face-smile-big.png'}else{'pics/face-sad.png'}} MouseRegion { anchors.fill: parent onClicked: { reset() } diff --git a/examples/declarative/minehunt/pics/face-sad.png b/examples/declarative/minehunt/pics/face-sad.png new file mode 100644 index 0000000..cf00aaf Binary files /dev/null and b/examples/declarative/minehunt/pics/face-sad.png differ diff --git a/examples/declarative/minehunt/pics/face-smile-big.png b/examples/declarative/minehunt/pics/face-smile-big.png new file mode 100644 index 0000000..f9c2335 Binary files /dev/null and b/examples/declarative/minehunt/pics/face-smile-big.png differ diff --git a/examples/declarative/minehunt/pics/face-smile.png b/examples/declarative/minehunt/pics/face-smile.png new file mode 100644 index 0000000..3d66d72 Binary files /dev/null and b/examples/declarative/minehunt/pics/face-smile.png differ diff --git a/examples/declarative/minehunt/pics/frown.png b/examples/declarative/minehunt/pics/frown.png deleted file mode 100644 index 52684b3..0000000 Binary files a/examples/declarative/minehunt/pics/frown.png and /dev/null differ diff --git a/examples/declarative/minehunt/pics/glee.png b/examples/declarative/minehunt/pics/glee.png deleted file mode 100644 index 59ea583..0000000 Binary files a/examples/declarative/minehunt/pics/glee.png and /dev/null differ diff --git a/examples/declarative/minehunt/pics/smile.png b/examples/declarative/minehunt/pics/smile.png deleted file mode 100644 index ccd52cd..0000000 Binary files a/examples/declarative/minehunt/pics/smile.png and /dev/null differ -- cgit v0.12 From d02cc90ec24fd30d1440e06eb443eafb221cdbe7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 13:25:46 +1000 Subject: Fix QmlComponent::isError() after QmlComponent::create() --- src/declarative/qml/qmlcomponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 66440f5..1e167d5 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -190,10 +190,10 @@ QmlComponent::Status QmlComponent::status() const if (d->typeData) return Loading; - else if (d->engine && d->cc) - return Ready; else if (!d->errors.isEmpty()) return Error; + else if (d->engine && d->cc) + return Ready; else return Null; } -- cgit v0.12 From 6089208e78bdcb0091c0ba0bc2fbd2a4fc0806de Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 13:48:29 +1000 Subject: Remove QML XML support --- src/declarative/qml/qml.pri | 2 - src/declarative/qml/qmlcomponent.cpp | 11 - src/declarative/qml/qmlcomponent_p.h | 1 - src/declarative/qml/qmlscriptparser.cpp | 19 -- src/declarative/qml/qmlxmlparser.cpp | 391 -------------------------- src/declarative/qml/qmlxmlparser_p.h | 89 ------ tools/qmlconv/qmlconv.cpp | 482 -------------------------------- tools/qmlconv/qmlconv.pro | 10 - 8 files changed, 1005 deletions(-) delete mode 100644 src/declarative/qml/qmlxmlparser.cpp delete mode 100644 src/declarative/qml/qmlxmlparser_p.h delete mode 100644 tools/qmlconv/qmlconv.cpp delete mode 100644 tools/qmlconv/qmlconv.pro diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 69a1461..5198264 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -8,7 +8,6 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlcontext.cpp \ qml/qmlcustomparser.cpp \ qml/qmlpropertyvaluesource.cpp \ - qml/qmlxmlparser.cpp \ qml/qmlproxymetaobject.cpp \ qml/qmlvme.cpp \ qml/qmlcompiler.cpp \ @@ -37,7 +36,6 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcustomparser_p_p.h \ qml/qmlpropertyvaluesource.h \ qml/qmlboundsignal_p.h \ - qml/qmlxmlparser_p.h \ qml/qmlparserstatus.h \ qml/qmlproxymetaobject_p.h \ qml/qmlcompiledcomponent_p.h \ diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 1e167d5..b1beb9c 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -60,17 +60,6 @@ QT_BEGIN_NAMESPACE class QByteArray; -bool QmlComponentPrivate::isXml(const QByteArray &ba) -{ - for (int i = 0; i < ba.size(); ++i) { - char c = ba.at(i); - if (c == ' ' || c == '\n' || c == '\r' || c == '\t') - continue; - return (c == '<'); - } - return true; -} - /*! \class QmlComponent \brief The QmlComponent class encapsulates a QML component description. diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index 0507958..6a5345e 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -82,7 +82,6 @@ public: QmlEngine *engine; void clear(); - static bool isXml(const QByteArray &); }; #endif // QMLCOMPONENT_P_H diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 618eb2e..d0051ac 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -1,6 +1,5 @@ #include "qmlscriptparser_p.h" -#include "qmlxmlparser_p.h" #include "qmlparser_p.h" #include "parser/javascriptengine_p.h" @@ -562,24 +561,6 @@ QmlScriptParser::~QmlScriptParser() bool QmlScriptParser::parse(const QByteArray &data, const QUrl &url) { - if (QmlComponentPrivate::isXml(data)) { - // parse using the XML parser. - QmlXmlParser xmlParser; - if (xmlParser.parse(data, url)) { - _nameSpacePaths = xmlParser.nameSpacePaths(); - root = xmlParser.takeTree(); - _typeNames = xmlParser.types(); - return true; - } - - QmlError error; - error.setUrl(url); - error.setDescription(xmlParser.errorDescription()); - _errors << error; - - return false; - } - const QString fileName = url.toString(); QTextStream stream(data, QIODevice::ReadOnly); diff --git a/src/declarative/qml/qmlxmlparser.cpp b/src/declarative/qml/qmlxmlparser.cpp deleted file mode 100644 index 35d2c0e..0000000 --- a/src/declarative/qml/qmlxmlparser.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmlxmlparser_p.h" -#include "qmlcustomparser_p.h" -#include -#include -#include -#include "qmlparser_p.h" -#include -#include - -QT_BEGIN_NAMESPACE -using namespace QmlParser; - -struct QmlXmlParserState { - QmlXmlParserState() : object(0), property(0) {} - QmlXmlParserState(Object *o) : object(o), property(0) {} - QmlXmlParserState(Object *o, Property *p) : object(o), property(p) {} - - Object *object; - Property *property; -}; - -struct QmlXmlParserStateStack : public QStack -{ - void pushObject(Object *obj) - { - push(QmlXmlParserState(obj)); - } - - void pushProperty(const QString &name, int lineNumber) - { - const QmlXmlParserState &state = top(); - if (state.property) { - QmlXmlParserState s(state.property->getValue(), - state.property->getValue()->getProperty(name.toLatin1())); - s.property->line = lineNumber; - push(s); - } else { - QmlXmlParserState s(state.object, - state.object->getProperty(name.toLatin1())); - s.property->line = lineNumber; - push(s); - } - } -}; - -QmlXmlParser::~QmlXmlParser() -{ - if (root) - root->release(); -} - -QmlXmlParser::QmlXmlParser() -: root(0) -{ -} - -static QString flatXml(QXmlStreamReader& reader) -{ - QString result; - int depth=0; - QStringRef ns = reader.namespaceUri(); - while (depth>=0) { - switch (reader.tokenType()) { - case QXmlStreamReader::StartElement: - result += QLatin1Char('<'); - result += reader.name(); - if (reader.namespaceUri() != ns || depth==0) { - result += QLatin1String(" xmlns=\""); - result += reader.namespaceUri(); - result += QLatin1Char('"'); - } - foreach(QXmlStreamAttribute attr, reader.attributes()) { - result += QLatin1Char(' '); - result += attr.name(); - result += QLatin1String("=\""); - result += attr.value(); // XXX escape - result += QLatin1Char('"'); - } - result += QLatin1Char('>'); - ++depth; - break; - case QXmlStreamReader::EndElement: - result += QLatin1String("'); - --depth; - break; - case QXmlStreamReader::Characters: - result += reader.text(); - break; - default: - reader.raiseError(QLatin1String("Only StartElement, EndElement, and Characters permitted")); - break; - } - if (depth>=0) - reader.readNext(); - } - return result; -} - -bool QmlXmlParser::parse(const QByteArray &data, const QUrl &url) -{ -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxPerfTimer pt; -#endif - - QString fileDisplayName; - if (url.isEmpty()) { - fileDisplayName = QLatin1String(""); - } else if (url.scheme() == QLatin1String("file")) { - fileDisplayName = url.toLocalFile(); - } else { - fileDisplayName = url.toString(); - } - if (data.isEmpty()) { - _error = QLatin1String("No Qml was specified for parsing @") + fileDisplayName; - return false; - } - - QmlXmlParserStateStack states; - - QXmlStreamReader reader; - reader.addData(data); - - while(!reader.atEnd()) { - switch(reader.readNext()) { - case QXmlStreamReader::Invalid: - case QXmlStreamReader::NoToken: - case QXmlStreamReader::StartDocument: - case QXmlStreamReader::EndDocument: - break; - - case QXmlStreamReader::StartElement: - { - QString name = reader.name().toString(); - QString nameSpace = reader.namespaceUri().toString(); - int line = reader.lineNumber(); - bool isType = name.at(0).isUpper() && !name.contains(QLatin1Char('.')); - QString qualifiedname; - if (!nameSpace.isEmpty()) { - qualifiedname = nameSpace; - qualifiedname += QLatin1Char('/'); - } - qualifiedname += name; - QByteArray qualifiednameL1 = qualifiedname.toLatin1(); - QXmlStreamAttributes attrs = reader.attributes(); - - if (isType) { - // Class - int typeId = _typeNames.indexOf(qualifiedname); - if (typeId == -1) { - typeId = _typeNames.count(); - _typeNames.append(qualifiedname); - } - - Object *obj = new Object; - obj->type = typeId; - obj->typeName = qualifiednameL1; - obj->line = line; - - QmlCustomParser *customparser = QmlMetaType::customParser(qualifiednameL1); - if (customparser) { - bool ok; - obj->custom = customparser->compile(reader, &ok); - if (reader.tokenType() != QXmlStreamReader::EndElement) { - reader.raiseError(QLatin1String("Parser for ") + qualifiedname + QLatin1String(" did not end on end element")); - ok = false; - } - if (!ok) { - delete obj; - break; - } - } - - - if (!root) { - root = obj; - states.pushObject(obj); - } else { - const QmlXmlParserState &state = states.top(); - Value *v = new Value; - v->object = obj; - v->line = line; - if (state.property) - state.property->addValue(v); - else - state.object->getDefaultProperty()->addValue(v); - states.pushObject(obj); - } - } else { - // Property - if (!root) { - reader.raiseError(QLatin1String("Can't have a property with no object")); - break; - } - QStringList str = name.split(QLatin1Char('.')); - for (int ii = 0; ii < str.count(); ++ii) { - QString s = str.at(ii); - states.pushProperty(s, line); - } - if (!nameSpace.isEmpty()) { - // Pass non-QML as flat text property value - const QmlXmlParserState &state = states.top(); - Value *v = new Value; - v->primitive = flatXml(reader); - v->line = line; - state.property->addValue(v); - } - } - - // (even custom parsed content gets properties set) - foreach(QXmlStreamAttribute attr, attrs) { - QStringList str = attr.name().toString().split(QLatin1Char('.')); - - for (int ii = 0; ii < str.count(); ++ii) { - QString s = str.at(ii); - states.pushProperty(s, line); - } - - const QmlXmlParserState &state = states.top(); - Value *v = new Value; - v->primitive = attr.value().toString(); - v->line = reader.lineNumber(); - state.property->addValue(v); - - for (int ii = str.count() - 1; ii >= 0; --ii) - states.pop(); - } - } - - // Custom parsers and namespaced properties move - // the reader to the end element, so we handle that - // BEFORE continuing. - // - if (reader.tokenType()!=QXmlStreamReader::EndElement) - break; - // ELSE fallthrough to EndElement... - case QXmlStreamReader::EndElement: - { - QString name = reader.name().toString(); - Q_ASSERT(!name.isEmpty()); - if (name.at(0).isUpper() && !name.contains(QLatin1Char('.'))) { - // Class - states.pop(); - } else { - // Property - QStringList str = name.split(QLatin1Char('.')); - for (int ii = 0; ii < str.count(); ++ii) - states.pop(); - } - } - break; - case QXmlStreamReader::Characters: - if (!reader.isWhitespace()) { - const QmlXmlParserState &state = states.top(); - Value *v = new Value; - v->primitive = reader.text().toString(); - v->line = reader.lineNumber(); - if (state.property) - state.property->addValue(v); - else - state.object->getDefaultProperty()->addValue(v); - } - break; - - case QXmlStreamReader::Comment: - case QXmlStreamReader::DTD: - case QXmlStreamReader::EntityReference: - break; - case QXmlStreamReader::ProcessingInstruction: - if (reader.processingInstructionTarget() == QLatin1String("qtfx")) { - QString str = reader.processingInstructionData().toString(); - QString token, data; - int idx = str.indexOf(QLatin1Char(':')); - if (-1 != idx) { - token = str.left(idx); - data = str.mid(idx + 1); - } else { - token = str; - } - token = token.trimmed(); - data = data.trimmed(); - - // - - if (token == QLatin1String("namespacepath")) { - int eq=data.indexOf(QLatin1Char('=')); - if (eq>=0) { - _nameSpacePaths.insertMulti(data.left(eq),data.mid(eq+1)); - } - } else { - str = str.trimmed(); - qWarning().nospace() << "Unknown processing instruction " << str.toLatin1().constData() << " @" << fileDisplayName.toLatin1().constData() << ":" << reader.lineNumber(); - } - } - break; - } - } - - if (reader.hasError()) { - if (root) { - root->release(); - root = 0; - } - _error = reader.errorString() + QLatin1String(" @") + fileDisplayName + - QLatin1String(":") + QString::number(reader.lineNumber()); - } - - return root != 0; -} - -QMap QmlXmlParser::nameSpacePaths() const -{ - return _nameSpacePaths; -} - -QStringList QmlXmlParser::types() const -{ - return _typeNames; -} - -QmlParser::Object *QmlXmlParser::tree() const -{ - return root; -} - -QmlParser::Object *QmlXmlParser::takeTree() -{ - QmlParser::Object *r = root; - root = 0; - return r; -} - -QString QmlXmlParser::errorDescription() const -{ - return _error; -} - -void QmlXmlParser::clear() -{ - if (root) { - root->release(); - root = 0; - } - _nameSpacePaths.clear(); - _typeNames.clear(); - _error.clear(); -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlxmlparser_p.h b/src/declarative/qml/qmlxmlparser_p.h deleted file mode 100644 index 9b45e28..0000000 --- a/src/declarative/qml/qmlxmlparser_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLXMLPARSER_P_H -#define QMLXMLPARSER_P_H - -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -namespace QmlParser { - class Object; -} - -class QByteArray; -class QmlXmlParser -{ -public: - QmlXmlParser(); - ~QmlXmlParser(); - - bool parse(const QByteArray &data, const QUrl &url=QUrl()); - QString errorDescription() const; - - QMap nameSpacePaths() const; - QStringList types() const; - - QmlParser::Object *tree() const; - QmlParser::Object *takeTree(); - - void clear(); - -private: - QMap _nameSpacePaths; - QmlParser::Object *root; - QStringList _typeNames; - QString _error; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QMLXMLPARSER_P_H - diff --git a/tools/qmlconv/qmlconv.cpp b/tools/qmlconv/qmlconv.cpp deleted file mode 100644 index 6e89530..0000000 --- a/tools/qmlconv/qmlconv.cpp +++ /dev/null @@ -1,482 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -static bool optionInPlace = false; - -class Reader -{ - QString outString; - QTextStream out; - QXmlStreamReader xml; - int depth; - bool supressIndent; - - QStringList knownListProperties; - inline QString depthString() {if (supressIndent) { supressIndent = false; return QString(); } - return QString(depth*4, QLatin1Char(' '));} - -public: - Reader(QIODevice *in) - :xml(in) { - - knownListProperties << "states" << "transitions" << "children" << "resources" - << "transform" << "notes"; - depth = 0; - supressIndent = false; - - out.setString(&outString); - - loop(); - - out.flush(); - - if (! optionInPlace) { - QTextStream print(stdout); - print << outString; - } - } - - QString output() const - { - return outString; - } - - void comment() - { - if (xml.isComment()) { - out << depthString() << "// " - << xml.text().toString().trimmed().replace(QRegExp("\n\\s*"),"\n"+depthString()+"// ") - << endl; - } - } - - void emptyLoop() { - while (!xml.atEnd()) { - xml.readNext(); - comment(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - return; - } - } - - void loop() - { - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - return; - else if (xml.tokenType() == QXmlStreamReader::StartElement) - startElement(); - else if (xml.tokenType() == QXmlStreamReader::ProcessingInstruction) { - if (xml.processingInstructionTarget() == QLatin1String("qtfx")) { - QString data = xml.processingInstructionData().toString().trimmed(); - if (data.startsWith(QLatin1String("namespacepath:="))) { - outString.prepend( QLatin1String("import \"") + data.mid(data.indexOf(QLatin1Char('='))+1) + QLatin1String("\"\n")); - } - } - } - comment(); - } - } - - void startElement() { - - if (!propertyChangeSet.isEmpty() - && xml.name() != "SetProperties" - && xml.name() != "SetProperty") { - clearPropertyChangeSet(); - } - - if (false && xml.name() == "properties") - startDeclareProperties(); - else if (false && xml.name() == "signals") - startDeclareSignals(); - else if (false && xml.name() == "states") - loop(); // ignore - else if (false && xml.name() == "transitions") - loop(); // ignore - else if (knownListProperties.contains(xml.name().toString())) - startList(); - else if (false && xml.name() == "SetProperties") - startSetProperties(); - else if (false && xml.name() == "SetProperty") - startSetProperty(); - else if (false && xml.name() == "ParentChange") - startParentChange(); - else if (true && xml.name() == "Connection") - startConnection(); - else if (false && xml.name() == "Script") - startScript(); - else if (xml.name().at(0).isLower() && xml.attributes().isEmpty()) - startObjectProperty(); - else - startItem(); - } - - static void possiblyRemoveBraces(QString *s) { - if (s->startsWith('{') && s->endsWith('}')) - *s = s->mid(1, s->length() - 2); - } - - static bool isNumber(const QString &s) { - bool ok = true; - s.toFloat(&ok); - return ok; - } - - static bool isSignalHandler(const QString &s) { - return s.size() > 3 - && s.startsWith("on") - && s.at(2).isUpper(); - } - - static bool isEnum(const QString &property, const QString &value) { - return !value.contains(' ') && (property == "vAlign" || property == "hAlign" - || property == "style"); - } - - static bool isIdentifier(const QString &s) { - if (s.isEmpty()) - return false; - if (!s.at(1).isLetter()) - return false; - for (int i = 1; i < s.size(); ++i) { - QChar c = s.at(i); - if (c.isLetterOrNumber() - || c == QLatin1Char('_') - || c == QLatin1Char('-')) - continue; - return false; - } - return true; - } - - - void setProperty(const QString &property, const QString &value, bool newline = true) { - QString v = value.trimmed(); - if (v.startsWith('{')) { - possiblyRemoveBraces(&v); - } else if (v == "true" - || v == "false" - || isNumber(v) - || property == "id" - || isEnum(property, value) - ) { - ; - } else if (isSignalHandler(property)) { - // if not a function name, create an anonymous function - if (!isIdentifier(v)) { - v.prepend("{ "); - v.append(" }"); - } - } else - - // if (property == "text" || property == "name" || value.contains(' ') - // || value.contains("/") || value.startsWith('#') - // || property == "filename" || property == "source" || property == "src" - // || property == "title" || property == "movieTitle" || property == "movieDescription" - // || property == "properties" || property == "fromState" || property == "toState" - // ) - { - v.prepend('\"'); - v.append('\"'); - } - -// QByteArray semiColon = ";"; -// if (v.endsWith(QLatin1Char('}')) || v.endsWith(QLatin1Char(';'))) -// semiColon.clear(); - - if (!newline) - out << property << ": " << v /* << semiColon.constData() */; - else - out << depthString() << property << ": " << v /* << semiColon.constData() */ << endl; - } - - - typedef QPair StringPair; - QList propertyChangeSet; - void startItem(bool inList = false) { - - QString name = xml.name().toString(); - - out << depthString() << name << " {" << endl; - ++depth; - - foreach (QXmlStreamAttribute attribute, xml.attributes()) { - setProperty(attribute.name().toString(), attribute.value().toString()); - } - - if (name == "Script") { - QString text = xml.readElementText(); - if (!text.trimmed().isEmpty()) { - out << text << endl; - } - } else { - loop(); - } - - if (name == "State") - clearPropertyChangeSet(); - - --depth; - out << depthString() << "}"; - if (!inList) - out << endl; - } - - void clearPropertyChangeSet() { - if (propertyChangeSet.isEmpty()) - return; - - out << depthString() << "PropertyChangeSet" << " {" << endl; - ++depth; - foreach(StringPair pair, propertyChangeSet) - setProperty(pair.first, pair.second); - --depth; - out << depthString() << "}" << endl; - propertyChangeSet.clear(); - } - - void startObjectProperty() { - - QString name = xml.name().toString(); - bool hasElements = false; - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - break; - if (xml.tokenType() == QXmlStreamReader::StartElement) { - hasElements = true; - out << depthString() << name << ": "; - supressIndent = true; - startElement(); - } else if (!hasElements && xml.tokenType() == QXmlStreamReader::Characters) { - if (!xml.text().toString().trimmed().isEmpty()) { - setProperty(name, xml.text().toString()); - } - } - comment(); - } - } - - void startDeclareProperty() { - out << depthString() << "public property "; - - if (xml.attributes().hasAttribute("type")) - out << "/* " << xml.attributes().value("type").toString() << " */ "; - - QString name = xml.attributes().value("name").toString(); - - if (xml.attributes().hasAttribute("value")) - setProperty(name, xml.attributes().value("value").toString(), false); - else out << name; - - QMap attributes; - foreach (QXmlStreamAttribute attribute, xml.attributes()) { - if (attribute.name() == "name" || attribute.name() == "value") - continue; - attributes.insert(attribute.name().toString(), attribute.value().toString()); - } - out << endl; - emptyLoop(); - } - - void startDeclareProperties() { - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - return; - if (xml.tokenType() == QXmlStreamReader::StartElement) { - if (xml.name() == "Property") - startDeclareProperty(); - } - comment(); - } - } - - void startDeclareSignal() { - out << depthString() << "public signal " << xml.attributes().value("name").toString() << endl; - emptyLoop(); - } - - void startDeclareSignals() { - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - return; - if (xml.tokenType() == QXmlStreamReader::StartElement) { - if (xml.name() == "Signal") - startDeclareSignal(); - } - comment(); - } - } - - - void startSetProperties() { - QString target = xml.attributes().value("target").toString(); - possiblyRemoveBraces(&target); - foreach (QXmlStreamAttribute attribute, xml.attributes()) { - if (attribute.name() == "target") - continue; - propertyChangeSet += StringPair(target + "." + attribute.name().toString(), attribute.value().toString()); - } - emptyLoop(); - } - - void startSetProperty() { - QString target = xml.attributes().value("target").toString(); - possiblyRemoveBraces(&target); - propertyChangeSet += StringPair(target + "." + xml.attributes().value("property").toString(), - xml.attributes().value("value").toString()); - - emptyLoop(); - } - - void startParentChange() { - QString target = xml.attributes().value("target").toString(); - possiblyRemoveBraces(&target); - - out << depthString() << "ParentChangeSet" << " {" << endl; - ++depth; - setProperty(target + ".parent", xml.attributes().value("parent").toString()); - --depth; - out << depthString() << "}" << endl; - -// propertyChangeSet += StringPair(target + ".moveToParent", xml.attributes().value("parent").toString()); - - emptyLoop(); - } - - void startConnection() { - QString sender = xml.attributes().value("sender").toString(); - possiblyRemoveBraces(&sender); - out << depthString() << "Connection {" << endl; - ++depth; - if (! sender.isEmpty()) - out << depthString() << "sender: " << sender << endl; - if (xml.attributes().hasAttribute("signal")) - out << depthString() << "signal: \"" << xml.attributes().value("signal").toString() << '"' << endl; - if (xml.attributes().hasAttribute("script")) { - out << depthString() << "script: { " << xml.attributes().value("script").toString() << " }" << endl; - --depth; - out << depthString() << "}" << endl; - } else { - QString text; - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - break; - else if (xml.tokenType() == QXmlStreamReader::Characters) - text.append(xml.text()); - } - - out << depthString() << "script: {" << endl; - foreach (QString line, text.split(QLatin1Char('\n'))) { - out << depthString() << line << endl; - } - out << depthString() << "}" << endl; - --depth; - out << depthString() << "}" << endl; - } - emptyLoop(); - } - - void startScript() { - if (xml.attributes().hasAttribute(QLatin1String("src"))) { - /* - QString import; - QTextStream ts(&import); - ts << "import \""; - ts << xml.attributes().value(QLatin1String("src")).toString(); - ts << "\"" << endl; - ts.flush(); - outString.prepend(import); - */ - } - QString text = xml.readElementText(); - if (!text.trimmed().isEmpty()) { - out << text << endl; - } - if (xml.tokenType() != QXmlStreamReader::EndElement) - emptyLoop(); - } - - void startList() - { - out << depthString() << xml.name().toString() << ": [" << endl; - ++depth; - bool needComma = false; - - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::EndElement) - break; - if (xml.tokenType() == QXmlStreamReader::StartElement) { - if (needComma) - out << "," << endl; - startItem(true); - needComma = true; - } - comment(); - } - - out << endl; - --depth; - out << depthString() << "]" << endl; - } - -}; - - - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - - QStringList args = a.arguments(); - args.removeFirst(); - - if (!args.isEmpty() && args.first() == QLatin1String("-i")) { - optionInPlace = true; - args.removeFirst(); - } - - if (args.isEmpty() && optionInPlace) { - qWarning() << "Usage: qmlconv [ [-i] filename ]"; - exit(1); - } - - const QString fileName = args.isEmpty() ? QString("-") : args.first(); - - QFile file(fileName); - if (fileName == "-") { - file.open(0,QIODevice::ReadOnly); - } else { - if (! file.open(QIODevice::ReadOnly)) { - qWarning() << "qmlconv: no input file"; - exit(1); - } - } - - Reader r(&file); - file.close(); - - if (optionInPlace) { - if (! file.open(QFile::WriteOnly)) { - qWarning() << "qmlconv: cannot open file" << qPrintable(fileName); - exit(1); - } - - QTextStream out(&file); - out << r.output(); - file.close(); - } - - return 0; -} diff --git a/tools/qmlconv/qmlconv.pro b/tools/qmlconv/qmlconv.pro deleted file mode 100644 index 331f4ee..0000000 --- a/tools/qmlconv/qmlconv.pro +++ /dev/null @@ -1,10 +0,0 @@ -DESTDIR = ../../bin -QT -= gui -# Input -SOURCES += qmlconv.cpp - -target.path=$$[QT_INSTALL_BINS] -INSTALLS += target - -CONFIG += console -macx:CONFIG -= app_bundle -- cgit v0.12 From f062be7569804461dad94d5b80dc0b87298fd5eb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 14:00:03 +1000 Subject: Remove XML custom parser support --- .../phonebrowser/dummydata/PhonesModel.qml | 2 +- .../declarative/pathview/dummydata/MenuModel.qml | 2 +- .../contacts/dummydata/contactModel.qml | 2 +- examples/declarative/easing/easing.qml | 2 +- .../declarative/listview/dummydata/MyPetsModel.qml | 2 +- .../declarative/listview/dummydata/Recipies.qml | 2 +- examples/declarative/velocity/velocity.qml | 2 +- src/declarative/qml/qmlcompiler.cpp | 26 +-- src/declarative/qml/qmlcustomparser_p.h | 17 -- src/declarative/qml/qmlinstruction.cpp | 3 - src/declarative/qml/qmlinstruction_p.h | 5 - src/declarative/qml/qmlvme.cpp | 21 --- src/declarative/util/qmllistmodel.cpp | 180 +-------------------- 13 files changed, 17 insertions(+), 249 deletions(-) diff --git a/demos/declarative/phonebrowser/dummydata/PhonesModel.qml b/demos/declarative/phonebrowser/dummydata/PhonesModel.qml index eb68fdb..8d9ed97 100644 --- a/demos/declarative/phonebrowser/dummydata/PhonesModel.qml +++ b/demos/declarative/phonebrowser/dummydata/PhonesModel.qml @@ -1,4 +1,4 @@ -ListModel2 { +ListModel { id: "PhonesModel" ListElement { diff --git a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml index 5b973d7..44cdaf0 100644 --- a/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml +++ b/doc/src/snippets/declarative/pathview/dummydata/MenuModel.qml @@ -1,4 +1,4 @@ -ListModel2 { +ListModel { id: MenuModel ListElement { name: "Bill Jones" diff --git a/examples/declarative/contacts/dummydata/contactModel.qml b/examples/declarative/contacts/dummydata/contactModel.qml index 48b2fd9..53f6b7b 100644 --- a/examples/declarative/contacts/dummydata/contactModel.qml +++ b/examples/declarative/contacts/dummydata/contactModel.qml @@ -1,4 +1,4 @@ -ListModel2 { +ListModel { ListElement { firstName: "Aaron" lastName: "Kennedy" diff --git a/examples/declarative/easing/easing.qml b/examples/declarative/easing/easing.qml index 32c1b9b..af675d1 100644 --- a/examples/declarative/easing/easing.qml +++ b/examples/declarative/easing/easing.qml @@ -4,7 +4,7 @@ Rect { height: Layout.height color: "white" - ListModel2 { + ListModel { id: EasingTypes ListElement { type: "easeLinear" } ListElement { type: "easeInQuad" } diff --git a/examples/declarative/listview/dummydata/MyPetsModel.qml b/examples/declarative/listview/dummydata/MyPetsModel.qml index 1c96b7f..4d76ff4 100644 --- a/examples/declarative/listview/dummydata/MyPetsModel.qml +++ b/examples/declarative/listview/dummydata/MyPetsModel.qml @@ -1,6 +1,6 @@ // ListModel allows free form list models to be defined and populated. // Be sure to name the file the same as the id. -ListModel2 { +ListModel { id: MyListElementsModel ListElement { name: "Polly" diff --git a/examples/declarative/listview/dummydata/Recipies.qml b/examples/declarative/listview/dummydata/Recipies.qml index 8f464da..3f2ab48 100644 --- a/examples/declarative/listview/dummydata/Recipies.qml +++ b/examples/declarative/listview/dummydata/Recipies.qml @@ -1,4 +1,4 @@ -ListModel2 { +ListModel { id: Recipies ListElement { title: "Pancakes" diff --git a/examples/declarative/velocity/velocity.qml b/examples/declarative/velocity/velocity.qml index ff95527..786f364 100644 --- a/examples/declarative/velocity/velocity.qml +++ b/examples/declarative/velocity/velocity.qml @@ -2,7 +2,7 @@ Rect { color: "lightSteelBlue" width: 800 height: 600 - ListModel2 { + ListModel { id: List ListElement { name: "Sunday" diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 37d7fa1..ec5903e 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -569,25 +569,13 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) } int createInstrIdx = output->bytecode.count(); - if (obj->type != -1 && output->types.at(obj->type).parser) { - QByteArray data = obj->custom; - int ref = output->indexForByteArray(data); - - QmlInstruction create; - create.type = QmlInstruction::CreateCustomObject; - create.line = obj->line; - create.createCustom.type = obj->type; - create.createCustom.data = ref; - output->bytecode << create; - } else { - // Create the object - QmlInstruction create; - create.type = QmlInstruction::CreateObject; - create.line = obj->line; - create.create.data = -1; - create.create.type = obj->type; - output->bytecode << create; - } + // Create the object + QmlInstruction create; + create.type = QmlInstruction::CreateObject; + create.line = obj->line; + create.create.data = -1; + create.create.type = obj->type; + output->bytecode << create; COMPILE_CHECK(compileDynamicPropertiesAndSignals(obj)); diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h index 0e6a619..e4e6089 100644 --- a/src/declarative/qml/qmlcustomparser_p.h +++ b/src/declarative/qml/qmlcustomparser_p.h @@ -98,26 +98,9 @@ class Q_DECLARATIVE_EXPORT QmlCustomParser public: virtual ~QmlCustomParser() {} - virtual QByteArray compile(QXmlStreamReader&, bool *ok)=0; virtual QByteArray compile(const QList &, bool *ok); - virtual QVariant create(const QByteArray &)=0; virtual void setCustomData(QObject *, const QByteArray &); - - struct Register { - Register(const char *name, QmlCustomParser *parser) { - qmlRegisterCustomParser(name, parser); - } - }; - template - struct Define { - static Register instance; - }; }; -#define QML_DEFINE_CUSTOM_PARSER(name, parserClass) \ - template<> QmlCustomParser::Register QmlCustomParser::Define::instance(# name, new parserClass); -#define QML_DEFINE_CUSTOM_PARSER_NS(namespacestring, name, parserClass) \ - template<> QmlCustomParser::Register QmlCustomParser::Define::instance(namespacestring "/" # name, new parserClass); - #define QML_DEFINE_CUSTOM_TYPE(TYPE, NAME, CUSTOMTYPE) \ template<> QmlPrivate::InstanceType QmlPrivate::Define::instance(qmlRegisterCustomType(#NAME, #TYPE, new CUSTOMTYPE)); diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 82924c8..52677c2 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -58,9 +58,6 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) case QmlInstruction::CreateObject: qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className; break; - case QmlInstruction::CreateCustomObject: - qWarning() << idx << "\t" << line << "\t" << "CREATE_CUSTOM\t\t" << instr->createCustom.type << "\t" << instr->createCustom.data << "\t\t" << types.at(instr->create.type).className; - break; case QmlInstruction::SetId: qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value); break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 922fc61..462f9e4 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -63,7 +63,6 @@ public: // top of the stack. Init, /* init */ CreateObject, /* create */ - CreateCustomObject, /* createCustom */ SetId, /* setId */ SetDefault, CreateComponent, /* createComponent */ @@ -180,10 +179,6 @@ public: int data; } storeMeta; struct { - int type; - int data; - } createCustom; - struct { int value; int save; } setId; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index a3bfd62..ad3d1d5 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -277,27 +277,6 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in } break; - case QmlInstruction::CreateCustomObject: - { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxCompilerTimer cc; -#endif - QVariant v = - types.at(instr.createCustom.type).parser->create(datas.at(instr.createCustom.data)); - // XXX - QObject *o = QmlMetaType::toQObject(v); - if (!o) - VME_EXCEPTION("Unable to create" << types.at(instr.create.type).className); - QmlEngine::setContextForObject(o, QmlContext::activeContext()); - - if (!stack.isEmpty()) { - QObject *parent = stack.top(); - o->setParent(parent); - } - stack.push(o); - } - break; - case QmlInstruction::SetId: { #ifdef Q_ENABLE_PERFORMANCE_LOG diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 4837180..6ad0cb9 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -190,8 +190,6 @@ ModelObject::ModelObject(ModelNode *node) { } -QML_DECLARE_TYPE(ListModel); -QML_DEFINE_TYPE(ListModel,ListModel); ListModel::ListModel(QObject *parent) : QListModelInterface(parent), _rolesOk(false), _root(0) { @@ -304,14 +302,10 @@ int ListModel::count() const class ListModelParser : public QmlCustomParser { public: - virtual QByteArray compile(QXmlStreamReader& reader, bool *); QByteArray compile(const QList &, bool *ok); - virtual QVariant create(const QByteArray &); - bool compileProperty(const QmlCustomParserProperty &prop, QList &instr, QByteArray &data); void setCustomData(QObject *, const QByteArray &); }; -QML_DEFINE_CUSTOM_PARSER(ListModel, ListModelParser); bool ListModelParser::compileProperty(const QmlCustomParserProperty &prop, QList &instr, QByteArray &data) { @@ -462,13 +456,10 @@ void ListModelParser::setCustomData(QObject *obj, const QByteArray &d) } } -class ListModel2 : public ListModel -{ -Q_OBJECT -}; -QML_DECLARE_TYPE(ListModel2); -QML_DEFINE_CUSTOM_TYPE(ListModel2, ListModel2, ListModelParser); +QML_DECLARE_TYPE(ListModel); +QML_DEFINE_CUSTOM_TYPE(ListModel, ListModel, ListModelParser); +// ### FIXME class ListElement : public QObject { Q_OBJECT @@ -512,170 +503,5 @@ ModelNode::~ModelNode() if (modelCache) { delete modelCache; modelCache = 0; } } -QByteArray ListModelParser::compile(QXmlStreamReader& reader, bool *ok) -{ - *ok = true; - - QByteArray data; - QList instr; - int depth=0; - - while(!reader.atEnd() && depth >= 0) { - switch(reader.readNext()) { - case QXmlStreamReader::StartElement: - { - QStringRef name = reader.name(); - bool isType = name.at(0).isUpper(); - - if (isType) { - ListInstruction li; - li.type = ListInstruction::Push; - li.dataIdx = -1; - instr << li; - - for (int i = 0; i < reader.attributes().count(); ++i) { - const QXmlStreamAttribute &attr = reader.attributes().at(i); - QStringRef attrName = attr.name(); - QStringRef attrValue = attr.value(); - - ListInstruction li; - int ref = data.count(); - data.append(attrName.toString().toLatin1()); - data.append('\0'); - li.type = ListInstruction::Set; - li.dataIdx = ref; - instr << li; - - ref = data.count(); - data.append(attrValue.toString().toLatin1()); - data.append('\0'); - li.type = ListInstruction::Value; - li.dataIdx = ref; - instr << li; - - li.type = ListInstruction::Pop; - li.dataIdx = -1; - instr << li; - } - } else { - ListInstruction li; - int ref = data.count(); - data.append(name.toString().toLatin1()); - data.append('\0'); - li.type = ListInstruction::Set; - li.dataIdx = ref; - instr << li; - } - } - ++depth; - break; - case QXmlStreamReader::EndElement: - { - ListInstruction li; - li.type = ListInstruction::Pop; - li.dataIdx = -1; - instr << li; - --depth; - } - break; - case QXmlStreamReader::Characters: - if (!reader.isWhitespace()) { - int ref = data.count(); - QByteArray d = reader.text().toString().toLatin1(); - d.append('\0'); - data.append(d); - - ListInstruction li; - li.type = ListInstruction::Value; - li.dataIdx = ref; - instr << li; - } - break; - - case QXmlStreamReader::Invalid: - case QXmlStreamReader::NoToken: - case QXmlStreamReader::StartDocument: - case QXmlStreamReader::EndDocument: - case QXmlStreamReader::Comment: - case QXmlStreamReader::DTD: - case QXmlStreamReader::EntityReference: - case QXmlStreamReader::ProcessingInstruction: - break; - } - } - - if (reader.hasError()) - *ok = true; - - if (!*ok) - return QByteArray(); - - int size = sizeof(ListModelData) + - instr.count() * sizeof(ListInstruction) + - data.count(); - - QByteArray rv; - rv.resize(size); - - ListModelData *lmd = (ListModelData *)rv.data(); - lmd->dataOffset = sizeof(ListModelData) + - instr.count() * sizeof(ListInstruction); - lmd->instrCount = instr.count(); - for (int ii = 0; ii < instr.count(); ++ii) - lmd->instructions()[ii] = instr.at(ii); - ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count()); - - return rv; -} - -QVariant ListModelParser::create(const QByteArray &d) -{ - ListModel *rv = new ListModel; - ModelNode *root = new ModelNode; - rv->_root = root; - QStack nodes; - nodes << root; - - const ListModelData *lmd = (const ListModelData *)d.constData(); - const char *data = ((const char *)lmd) + lmd->dataOffset; - - for (int ii = 0; ii < lmd->instrCount; ++ii) { - const ListInstruction &instr = lmd->instructions()[ii]; - - switch(instr.type) { - case ListInstruction::Push: - { - ModelNode *n = nodes.top(); - ModelNode *n2 = new ModelNode; - n->values << qVariantFromValue(n2); - nodes.push(n2); - } - break; - - case ListInstruction::Pop: - nodes.pop(); - break; - - case ListInstruction::Value: - { - ModelNode *n = nodes.top(); - n->values.append(QByteArray(data + instr.dataIdx)); - } - break; - - case ListInstruction::Set: - { - ModelNode *n = nodes.top(); - ModelNode *n2 = new ModelNode; - n->properties.insert(QLatin1String(data + instr.dataIdx), n2); - nodes.push(n2); - } - break; - } - } - - return QVariant::fromValue(rv); -} - QT_END_NAMESPACE #include "qmllistmodel.moc" -- cgit v0.12 From d778d86065e08cf55fdf70a491f17c61ff93705c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 14:05:03 +1000 Subject: Remove magic "properties" and "signals" property support New properties and signals should be defined using the QML syntax: [default] property [: ] signal --- src/declarative/qml/qmlcompiler.cpp | 238 +----------------------------------- src/declarative/qml/qmlcompiler_p.h | 5 - src/declarative/qml/qmlparser.cpp | 5 +- src/declarative/qml/qmlparser_p.h | 4 - 4 files changed, 3 insertions(+), 249 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index ec5903e..b8f3921 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -64,17 +64,6 @@ #include "qmlscriptparser_p.h" QT_BEGIN_NAMESPACE -/* - New properties and signals can be added to any QObject type from QML. - - - - metatype && obj->metatype->indexOfProperty(PROPERTIES_NAME) != -1) - ignoreProperties = true; - if (obj->metatype && obj->metatype->indexOfProperty(SIGNALS_NAME) != -1) - ignoreSignals = true; - - Property *propertiesProperty = ignoreProperties?0:obj->getProperty(PROPERTIES_NAME, false); - Property *signalsProperty = ignoreSignals?0:obj->getProperty(SIGNALS_NAME, false); - - if (propertiesProperty) { - obj->dynamicPropertiesProperty = propertiesProperty; - obj->properties.remove(PROPERTIES_NAME); - } - if (signalsProperty) { - obj->dynamicSignalsProperty = signalsProperty; - obj->properties.remove(SIGNALS_NAME); - } - int createInstrIdx = output->bytecode.count(); // Create the object QmlInstruction create; @@ -602,9 +570,7 @@ bool QmlCompiler::compileObject(Object *obj, int ctxt) QList customProps; foreach(Property *prop, obj->properties) { - if (!ignoreProperties && prop->name == PROPERTIES_NAME) { - } else if (!ignoreSignals && prop->name == SIGNALS_NAME) { - } else if (prop->name.length() >= 3 && prop->name.startsWith("on") && + if (prop->name.length() >= 3 && prop->name.startsWith("on") && ('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) { if (!isCustomParser) { COMPILE_CHECK(compileSignal(prop, obj)); @@ -1246,209 +1212,9 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, return true; } -bool QmlCompiler::findDynamicProperties(QmlParser::Property *prop, - QmlParser::Object *obj) -{ - QList definedProperties; - - struct TypeNameToType { - const char *name; - Object::DynamicProperty::Type type; - } propTypeNameToTypes[] = { - { "", Object::DynamicProperty::Variant }, - { "int", Object::DynamicProperty::Int }, - { "bool", Object::DynamicProperty::Bool }, - { "double", Object::DynamicProperty::Real }, - { "real", Object::DynamicProperty::Real }, - { "string", Object::DynamicProperty::String }, - { "color", Object::DynamicProperty::Color }, - { "date", Object::DynamicProperty::Date }, - { "variant", Object::DynamicProperty::Variant } - }; - const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) / - sizeof(propTypeNameToTypes[0]); - - - if (prop->value) - COMPILE_EXCEPTION("Invalid property specification"); - - bool seenDefault = false; - for (int ii = 0; ii < prop->values.count(); ++ii) { - QmlParser::Value *val = prop->values.at(ii); - if (!val->object) - COMPILE_EXCEPTION("Invalid property specification"); - - QmlParser::Object *obj = val->object; - if (obj->type == -1 || output->types.at(obj->type).className != "Property") - COMPILE_EXCEPTION("Use Property tag to specify properties"); - - - enum Seen { None = 0, Name = 0x01, - Type = 0x02, Value = 0x04, - ValueChanged = 0x08, - Default = 0x10 } seen = None; - - Object::DynamicProperty propDef; - - for (QHash::ConstIterator iter = - obj->properties.begin(); - iter != obj->properties.end(); - ++iter) { - - QmlParser::Property *property = *iter; - if (property->name == "name") { - if (seen & Name) - COMPILE_EXCEPTION("May only specify Property name once"); - seen = (Seen)(seen | Name); - - if (property->value || property->values.count() != 1 || - property->values.at(0)->object) - COMPILE_EXCEPTION("Invalid Property name"); - - propDef.name = property->values.at(0)->primitive.toLatin1(); - - } else if (property->name == "type") { - if (seen & Type) - COMPILE_EXCEPTION("May only specify Property type once"); - seen = (Seen)(seen | Type); - - if (property->value || property->values.count() != 1 || - property->values.at(0)->object) - COMPILE_EXCEPTION("Invalid Property type"); - - QString type = property->values.at(0)->primitive.toLower(); - bool found = false; - for (int ii = 0; !found && ii < propTypeNameToTypesCount; ++ii) { - if (type == QLatin1String(propTypeNameToTypes[ii].name)){ - found = true; - propDef.type = propTypeNameToTypes[ii].type; - } - - } - - if (!found) - COMPILE_EXCEPTION("Invalid Property type"); - - } else if (property->name == "value") { - if (seen & Value) - COMPILE_EXCEPTION("May only specify Property value once"); - seen = (Seen)(seen | Value); - - propDef.defaultValue = property; - } else if (property->name == "onValueChanged") { - if (seen & ValueChanged) - COMPILE_EXCEPTION("May only specify Property onValueChanged once"); - seen = (Seen)(seen | ValueChanged); - - if (property->value || property->values.count() != 1 || - property->values.at(0)->object) - COMPILE_EXCEPTION("Invalid Property onValueChanged"); - - propDef.onValueChanged = property->values.at(0)->primitive; - - } else if (property->name == "default") { - if (seen & Default) - COMPILE_EXCEPTION("May only specify Property default once"); - seen = (Seen)(seen | Default); - if (property->value || property->values.count() != 1 || - property->values.at(0)->object) - COMPILE_EXCEPTION("Invalid Property default"); - - bool defaultValue = - QmlStringConverters::boolFromString(property->values.at(0)->primitive); - propDef.isDefaultProperty = defaultValue; - if (defaultValue) { - if (seenDefault) - COMPILE_EXCEPTION("Only one property may be the default"); - seenDefault = true; - } - - } else { - COMPILE_EXCEPTION("Invalid Property property"); - } - - } - if (obj->defaultProperty) { - if (seen & Value) - COMPILE_EXCEPTION("May only specify Property value once"); - - seen = (Seen)(seen | Value); - propDef.defaultValue = obj->defaultProperty; - } - - if (!(seen & Name)) - COMPILE_EXCEPTION("Must specify Property name"); - - definedProperties << propDef; - } - - obj->dynamicProperties << definedProperties; - return true; -} - -bool QmlCompiler::findDynamicSignals(QmlParser::Property *sigs, - QmlParser::Object *obj) -{ - QList definedSignals; - - if (sigs->value) - COMPILE_EXCEPTION("Invalid signal specification"); - - for (int ii = 0; ii < sigs->values.count(); ++ii) { - QmlParser::Value *val = sigs->values.at(ii); - if (!val->object) - COMPILE_EXCEPTION("Invalid signal specification"); - - QmlParser::Object *obj = val->object; - if (obj->type == -1 || output->types.at(obj->type).className != "Signal") - COMPILE_EXCEPTION("Use Signal tag to specify signals"); - - enum Seen { None = 0, Name = 0x01 } seen = None; - Object::DynamicSignal sigDef; - - for (QHash::ConstIterator iter = - obj->properties.begin(); - iter != obj->properties.end(); - ++iter) { - - QmlParser::Property *property = *iter; - if (property->name == "name") { - if (seen & Name) - COMPILE_EXCEPTION("May only specify Signal name once"); - seen = (Seen)(seen | Name); - - if (property->value || property->values.count() != 1 || - property->values.at(0)->object) - COMPILE_EXCEPTION("Invalid Signal name"); - - sigDef.name = property->values.at(0)->primitive.toLatin1(); - - } else { - COMPILE_EXCEPTION("Invalid Signal property"); - } - - } - - if (obj->defaultProperty) - COMPILE_EXCEPTION("Invalid Signal property"); - - if (!(seen & Name)) - COMPILE_EXCEPTION("Must specify Signal name"); - - definedSignals << sigDef; - } - - obj->dynamicSignals << definedSignals; - return true; -} - bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj) { - if (obj->dynamicPropertiesProperty) - findDynamicProperties(obj->dynamicPropertiesProperty, obj); - if (obj->dynamicSignalsProperty) - findDynamicSignals(obj->dynamicSignalsProperty, obj); - + // ### FIXME - Check that there is only one default property etc. if (obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty()) return true; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index cc1a9e9..4acdcfa 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -163,11 +163,6 @@ private: QmlParser::Value *value, int ctxt); - bool findDynamicProperties(QmlParser::Property *prop, - QmlParser::Object *obj); - bool findDynamicSignals(QmlParser::Property *sigs, - QmlParser::Object *obj); - bool compileDynamicPropertiesAndSignals(QmlParser::Object *obj); void compileBinding(const QString &, QmlParser::Property *prop, int ctxt, const QMetaObject *, qint64); diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 87c8434..d862315 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -63,8 +63,7 @@ QT_BEGIN_NAMESPACE using namespace QmlParser; QmlParser::Object::Object() -: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1), column(-1), - dynamicPropertiesProperty(0), dynamicSignalsProperty(0) +: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1), column(-1) { } @@ -73,8 +72,6 @@ QmlParser::Object::~Object() if (defaultProperty) defaultProperty->release(); foreach(Property *prop, properties) prop->release(); - if (dynamicPropertiesProperty) dynamicPropertiesProperty->release(); - if (dynamicSignalsProperty) dynamicSignalsProperty->release(); } const QMetaObject *Object::metaObject() const diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 17b367d6..aeacee8 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -124,10 +124,6 @@ namespace QmlParser QByteArray name; }; - // The "properties" property - Property *dynamicPropertiesProperty; - // The "signals" property - Property *dynamicSignalsProperty; // The list of dynamic properties described in the "properties" property QList dynamicProperties; // The list of dynamic signals described in the "signals" property -- cgit v0.12 From 0725ca189ad30ec54a2a7a054404a50f20e2bfed Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 14:55:09 +1000 Subject: Add warning text --- src/declarative/qml/qmlscriptparser.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index d0051ac..81315c3 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -522,7 +522,11 @@ bool ProcessAST::visit(AST::UiSourceElement *node) { QmlParser::Object *obj = currentObject(); if (! (obj && obj->typeName == "Script")) { - // ### warning + QmlError error; + error.setDescription("JavaScript declaration outside Script element"); + error.setLine(node->firstSourceLocation().startLine); + error.setColumn(node->firstSourceLocation().startColumn); + _parser->_errors << error; return false; } -- cgit v0.12 From e8f2cc813ba4faf41677f65c51a990eea5df4308 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 5 May 2009 14:58:06 +1000 Subject: Improve QML documentation viewing in Assistant. The element pages now load correctly. A separate QML 'book' is also generated, which will be targeted at non-C++ programmers. --- doc/doc.pri | 5 ++- doc/src/declarative/qmlfordesign.qdoc | 42 ------------------- doc/src/declarative/qmlreference.qdoc | 41 +++++++++++++++++++ tools/qdoc3/helpprojectwriter.cpp | 3 ++ tools/qdoc3/test/qml.qdocconf | 77 +++++++++++++++++++++++++++++++++++ tools/qdoc3/tree.cpp | 9 +++- 6 files changed, 131 insertions(+), 46 deletions(-) delete mode 100644 doc/src/declarative/qmlfordesign.qdoc create mode 100644 doc/src/declarative/qmlreference.qdoc create mode 100644 tools/qdoc3/test/qml.qdocconf diff --git a/doc/doc.pri b/doc/doc.pri index a4c77fe..367ef29 100644 --- a/doc/doc.pri +++ b/doc/doc.pri @@ -32,13 +32,14 @@ macx { ADP_DOCS_QDOCCONF_FILE = qt-build-docs.qdocconf } QT_DOCUMENTATION = ($$QDOC qt-api-only.qdocconf assistant.qdocconf designer.qdocconf \ - linguist.qdocconf qmake.qdocconf) && \ + linguist.qdocconf qmake.qdocconf qml.qdocconf) && \ (cd $$QT_BUILD_TREE && \ $$GENERATOR doc-build/html-qt/qt.qhp -o doc/qch/qt.qch && \ $$GENERATOR doc-build/html-assistant/assistant.qhp -o doc/qch/assistant.qch && \ $$GENERATOR doc-build/html-designer/designer.qhp -o doc/qch/designer.qch && \ $$GENERATOR doc-build/html-linguist/linguist.qhp -o doc/qch/linguist.qch && \ - $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch \ + $$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch && \ + $$GENERATOR doc-build/html-qml/qml.qhp -o doc/qch/qml.qch \ ) win32-g++:isEmpty(QMAKE_SH) { diff --git a/doc/src/declarative/qmlfordesign.qdoc b/doc/src/declarative/qmlfordesign.qdoc deleted file mode 100644 index 35e47df..0000000 --- a/doc/src/declarative/qmlfordesign.qdoc +++ /dev/null @@ -1,42 +0,0 @@ -/*! - \page qmlfordesigners.html - \title Qt Declarative for Designers - - \target qtdeclarativemainpage - - The Qt Declarative module provides a declarative framework for building - highly dynamic and fluid applications. It is targetted at the sorts of user - interface (and the sorts of hardware) in embedded devices such as phones, media - players, and set-top boxes. It is also appropriate for highly custom desktop - user-interfaces, or special elements in more traditional desktop - user-interfaces. - - Building fluid applications is done declaratively, rather than procedurally. - That is, you specify \e what the UI should look like and how it should behave - rather than specifying step-by-step \e how to build it. Specifying a UI declaratively - does not just include the layout of the interface items, but also the way each - individual item looks and behaves and the overall flow of the application. - - Getting Started: - \list - \o \l {qmlexamples}{Examples} - \o \l {tutorial}{Tutorial: 'Hello World'} - \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} - \endlist - - Core Features: - \list - \o \l {binding}{Data Binding} - \o \l {anchor-layout}{Layout Anchors} - \o \l {qmlanimation}{Animation} - \o \l {qmleffects}{Visual Effects} - \o \l {components}{Components} - \o \l {qmlmodules}{Modules} - \o \l {qmlfocus}{Keyboard Focus} - \endlist - - QML Reference: - \list - \o \l {elements}{Qml Elements} - \endlist -*/ diff --git a/doc/src/declarative/qmlreference.qdoc b/doc/src/declarative/qmlreference.qdoc new file mode 100644 index 0000000..9a63e50 --- /dev/null +++ b/doc/src/declarative/qmlreference.qdoc @@ -0,0 +1,41 @@ +/*! + \page qmlreference.html + \title Qml Reference + + \target qtdeclarativemainpage + + QML is a language for building highly dynamic and fluid applications. It is targetted at the sorts of user + interface (and the sorts of hardware) in embedded devices such as phones, media + players, and set-top boxes. It is also appropriate for highly custom desktop + user-interfaces, or special elements in more traditional desktop + user-interfaces. + + Building fluid applications is done declaratively, rather than procedurally. + That is, you specify \e what the UI should look like and how it should behave + rather than specifying step-by-step \e how to build it. Specifying a UI declaratively + does not just include the layout of the interface items, but also the way each + individual item looks and behaves and the overall flow of the application. + + Getting Started: + \list + \o \l {qmlexamples}{Examples} + \o \l {tutorial}{Tutorial: 'Hello World'} + \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} + \endlist + + Core Features: + \list + \o \l {binding}{Data Binding} + \o \l {anchor-layout}{Layout Anchors} + \o \l {qmlanimation}{Animation} + \o \l {qmleffects}{Visual Effects} + \o \l {components}{Components} + \o \l {qmlmodules}{Modules} + \o \l {qmlfocus}{Keyboard Focus} + \endlist + + QML Reference: + \list + \o \l {elements}{Qml Elements} + \endlist +*/ diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index 85bd898..16ee5f2 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -126,6 +126,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList subTypeHash["module"] = Node::Module; subTypeHash["page"] = Node::Page; subTypeHash["externalpage"] = Node::ExternalPage; +#ifdef QDOC_QML + subTypeHash["qmlclass"] = Node::QmlClass; +#endif QSet allSubTypes = QSet::fromList(subTypeHash.values()); diff --git a/tools/qdoc3/test/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf new file mode 100644 index 0000000..3a7d76a --- /dev/null +++ b/tools/qdoc3/test/qml.qdocconf @@ -0,0 +1,77 @@ +include(compat.qdocconf) +include(macros.qdocconf) +include(qt-cpp-ignore.qdocconf) +include(qt-html-templates.qdocconf) +include(qt-defines.qdocconf) + +project = Qml +description = Qml Reference Documentation +url = http://doc.qtsoftware.com/4.6 + +edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ + QtXmlPatterns QtTest +edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtSql QtSvg \ + QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \ + QtDesigner QtAssistant QAxContainer Phonon \ + QAxServer QtUiTools QtTest QtDBus +edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest +edition.DesktopLight.groups = -graphicsview-api + +qhp.projects = Qml + +qhp.Qml.file = qml.qhp +qhp.Qml.namespace = com.trolltech.qml.460 +qhp.Qml.virtualFolder = qdoc +qhp.Qml.indexTitle = Qml Reference + +# Files not referenced in any qdoc file +# See also extraimages.HTML +qhp.Qml.extraFiles = classic.css \ + images/qt-logo.png + +qhp.Qml.filterAttributes = qt 4.6.0 qtrefdoc +qhp.Qml.customFilters.Qt.name = Qt 4.6.0 +qhp.Qml.customFilters.Qt.filterAttributes = qt 4.6.0 +qhp.Qml.subprojects = classes +qhp.Qml.subprojects.classes.title = Elements +qhp.Qml.subprojects.classes.indexTitle = Qml Elements +qhp.Qml.subprojects.classes.selectors = fake:qmlclass +qhp.Qml.subprojects.classes.sortPages = true + +language = Cpp + +headerdirs = $QT_SOURCE_TREE/src/declarative +sourcedirs = $QT_SOURCE_TREE/src/declarative \ + $QT_SOURCE_TREE/doc/src/declarative + +sources += $QT_SOURCE_TREE/doc/src/tutorials/declarative.qdoc + +sources.fileextensions = "*.cpp *.qdoc" +examples.fileextensions = "*.cpp *.h *.js *.qml" + +exampledirs = $QT_SOURCE_TREE/doc/src \ + $QT_SOURCE_TREE/examples \ + $QT_SOURCE_TREE/examples/tutorials \ + $QT_SOURCE_TREE \ + $QT_SOURCE_TREE/qmake/examples \ + $QT_SOURCE_TREE/src/3rdparty/webkit/WebKit/qt/docs +imagedirs = $QT_SOURCE_TREE/doc/src/images \ + $QT_SOURCE_TREE/examples \ + $QT_SOURCE_TREE/doc/src/declarative/pics +outputdir = $QT_BUILD_TREE/doc-build/html-qml +tagfile = $QT_BUILD_TREE/doc-build/html-qml/qt.tags +base = file:$QT_BUILD_TREE/doc/html-qml + +HTML.stylesheets = classic.css + +HTML.postheader = "\n" \ + "\n" \ + "\n" \ + "" \ + "\n" \ + "
" \ + "" \ + "  " \ + "" \ + "Home" \ + "
" diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index 539db51..b91de65 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -1901,9 +1901,14 @@ QString Tree::fullDocumentLocation(const Node *node) const else return ""; } - else if (node->type() == Node::Fake) + else if (node->type() == Node::Fake) { +#ifdef QDOC_QML + if (node->subType() == Node::QmlClass) + return "qml-" + node->fileBase() + ".html"; + else +#endif return node->fileBase() + ".html"; - else if (node->fileBase().isEmpty()) + } else if (node->fileBase().isEmpty()) return ""; QString parentName; -- cgit v0.12 From 132830854a1b547666c1c65c7db1c6c089399637 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 5 May 2009 15:35:38 +1000 Subject: More doc conversion and cleanup. --- doc/src/declarative/anchor-layout.qdoc | 30 +++---- doc/src/declarative/animation.qdoc | 126 ++++++++++++++++++++--------- doc/src/declarative/basictypes.qdoc | 46 +++++------ doc/src/declarative/binding.qdoc | 20 ++--- doc/src/declarative/components.qdoc | 42 +++++++--- doc/src/declarative/cppitem.qdoc | 2 +- src/declarative/fx/qfxflipable.cpp | 4 +- src/declarative/fx/qfximage.cpp | 4 +- src/declarative/fx/qfxitem.cpp | 2 +- src/declarative/fx/qfxparticles.cpp | 18 ++--- src/declarative/fx/qfxreflectionfilter.cpp | 12 +-- src/declarative/fx/qfxshadowfilter.cpp | 2 +- src/declarative/fx/qfxtransform.cpp | 12 +-- 13 files changed, 191 insertions(+), 129 deletions(-) diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc index 2b1f081..9ff902ee 100644 --- a/doc/src/declarative/anchor-layout.qdoc +++ b/doc/src/declarative/anchor-layout.qdoc @@ -10,8 +10,8 @@ In additional to the more traditional Fx layouts GridLayout, HorizontalLayout, a The Fx anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write: \code - - +Rect { id: rect1; ... } +Rect { id: rect2; anchors.left: rect1.right; ... } \endcode In this case, the left edge of \e rect2 is bound to the right edge of rect1, producing the following: @@ -25,8 +25,8 @@ The anchoring system also allows you to specify margins and offsets. Margins spe The following example specifies a left margin: \code - - +Rect { id: rect1; ... } +Rect { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... } \endcode In this case, a margin of 5 pixels is reserved to the left of \e rect2, producing the following: @@ -36,8 +36,8 @@ In this case, a margin of 5 pixels is reserved to the left of \e rect2, producin You can specify multiple anchors. For example: \code - - +Rect { id: rect1; ... } +Rect { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... } \endcode \image edge3.png @@ -45,9 +45,9 @@ You can specify multiple anchors. For example: By specifying multiple horizontal or vertical anchors you can control the size of an item. For example: \code - - - +Rect { id: rect1; x: 0; ... } +Rect { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... } +Rect { id: rect3; x: 150; ... } \endcode \image edge4.png @@ -57,12 +57,12 @@ By specifying multiple horizontal or vertical anchors you can control the size o For performance reasons, you can only anchor an item to its siblings and direct parent. For example, the following anchor would be considered invalid and would produce a warning: \code - - - - - - +Item { id: group1 } + Rect { id: rect1; ... } +} +Item id: group2"> + Rect { id: rect2; anchors.left: rect1.right; ... } // invalid anchor! +} \endcode */ diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc index cd7d1b9..fb14fdc 100644 --- a/doc/src/declarative/animation.qdoc +++ b/doc/src/declarative/animation.qdoc @@ -29,19 +29,30 @@ The simplest form of animation is using \c <NumericAnimation/> The following example creates a bouncing effect: \code - - - - - - - - - - +Rect { + id: rect + width: 120 + height: 200 + color: "white" + Image { + id: img + source: "pics/qtlogo.png" + x: 60-img.width/2 + y: 200-img.height + y: SequentialAnimation { + running: true + repeat: true + NumericAnimation { + to: 200-img.height + easing: "easeOutBounce(amplitude:100)" + duration: 2000 + } + PauseAnimation { + duration: 1000 + } + } + } +} \endcode \image propanim.gif @@ -76,15 +87,28 @@ In QML: The following example shows a simple use of states. In the default state \c myrect is positioned at 0,0. In the 'moved' state it is positioned at 50,50. \code - - - - - - - - - +Item { + Rect { + id: myrect + width: 100 + height: 100 + } + states: [ + State { + name: "moved" + SetProperty { + target: myrect + property: "x" + value: 50 + } + SetProperty { + target: myrect + property: "y" + value: 50 + } + } + ] +} \endcode \section2 Transitions @@ -94,34 +118,56 @@ QML transitions describe animations to perform when state changes occur. For the previous example, a transition could describe how \c myrect moved from its initial position to its new position: \code - - - - - +transitions: [ + Transition { + NumericAnimation { + properties: "x,y" + easing: "easeOutBounce" + duration: 200 + } + } +] \endcode QML transitions can use selectors to determine which state changes a transition should apply to: \code - -... - +Transition { + fromState: "*" + toState: "Details" + ... +} \endcode Transitions can happen in parallel, in sequence, or in any combination of the two:; \code - - - - - - - - - - +Transition { + fromState: "*" + toState: "MyState" + reversible: true + SequentialAnimation { + ColorAnimation { + duration: 1000 + } + PauseAnimation { + duration: 1000 + } + ParallelAnimation { + NumericAnimation { + duration: 1000 + easing: "easeOutBounce" + target: box1 + properties: "x,y" + } + NumericAnimation { + duration: 1000 + target: box2 + properties: "x,y" + } + } + } +} \endcode \section1 Property Behaviors diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 0000c37..f7eee50 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -23,7 +23,7 @@ Setting ints looks like this: \code - + Item { width: 100; height:200 } \endcode \target basicqmlbool @@ -39,7 +39,7 @@ Setting bools looks like this: \code - + Item { focusable: true; clip: false } \endcode \note Technically bool treats an empty string, "false" and "0" as false and @@ -58,7 +58,7 @@ Setting reals looks like this: \code - + Item { x: -10; y: 100.8 } \endcode \note In QML all reals are stored in single precision, \l {http://en.wikipedia.org/wiki/IEEE_754}{IEEE floating point} format. @@ -76,7 +76,7 @@ Setting a string looks like this: \code - + Text { text: "Hello world!" } \endcode \raw HTML @@ -101,9 +101,9 @@ Setting a color looks like this: \code - - - + Rect { color: "steelblue" } + Rect { color: "#FF0000" } + Rect { color: "#800000FF" } \endcode \target basicqmlpoint @@ -118,7 +118,7 @@ Setting a point looks like this: \code - + Widget { pos: "50,50" } \endcode \target basicqmlsize @@ -133,7 +133,7 @@ Setting a size looks like this: \code - + Widget { size: "50x50" } \endcode \target basicqmlrectangle @@ -148,7 +148,7 @@ Setting a rectangle looks like this: \code - + Widget { geometry: "50,50,100x100" } \endcode \target basicqmldate @@ -163,7 +163,7 @@ Setting a date looks like this: \code - + DatePicker { minDate: "2000-01-01"; maxDate: "2020-12-31" } \endcode \target basicqmltime @@ -178,7 +178,7 @@ Setting a time looks like this: \code - + TimePicker { time: "14:22:15" } \endcode \target basicqmlfont @@ -199,7 +199,7 @@ Setting a font looks like this: \code - + Text { font.family: "Helvetica"; font.size: 13; font.bold: true } \endcode \target basicqmlaction @@ -220,9 +220,9 @@ Actions are used like this: \code - - - + MouseRegion { onClicked: someitem.someaction.trigger() } + State { name: "enabled"; when: someitem.someaction.enabled=='true' } + Text { text: someitem.someaction.text } \endcode \target basicqmlany @@ -252,13 +252,13 @@ For example, the \l Item class has a children list property that can be used like this: \code - - - - - - - + Item { + children [ + Item { id: child1 }, + Rect { id: child2 }, + Text { id: child3 } + ] + } \endcode \c child1, \c child2 and \c child3 will all be added to the children list in the order in which they appear. diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc index 1d4f9a1..2920d51 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/binding.qdoc @@ -5,23 +5,23 @@ Data binding provides a declarative way of specifying the data associated with objects, as well as the relationship between data of different objects. For example, you could bind the text of a label to the value of a slider: as the value of the slider changed, the label would be automatically updated with the new value. -Bindings are indicated in Qml through the use of brackets: \c {}. For example, the following produces two Rects of equal size (\c rect2 is bound to the size of \c rect1): +Bindings are created in Qml when an expression is assigned to a property. For example, the following produces two Rects of equal size (\c rect2 is bound to the size of \c rect1): \code - - +Rect { id: rect1; width: 100; height: 100 } +Rect { id: rect2; width: rect1.width; height: rect1.height } \endcode -There is also a special \c element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and Qml} for an example of this). The bindings above could be expressed using the \c element as: +There is also a special \l Bind element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and Qml} for an example of this). The bindings above could be expressed using the \l Bind element as: \code - - +Bind { target: rect2; property: "width"; value: rect1.width } +Bind { target: rect2; property: "height"; value: rect1.height } \endcode In addition to binding directly to a property, you can also bind to the results of expressions involving properties. For example: \code - - +Text { text: contact.firstname + ' ' + contact.lastname } +Image { source: if (contact.gender == "female") {"pics/female.png"} else {"pics/male.png"} } \endcode Relevant items can also be bound to the contents of a model - see \l ListView for an example of this. @@ -101,8 +101,8 @@ view->execute(); Finally, in Qml you can make the appropriate bindings, so in \c "MyUI.qml": \code - - +Slider { value: screen.brightness } +Bind { target: screen; property: "brightness"; value: slider.value } \endcode The \l QBindableMap class provides a convenient way to make data visible to the bind engine. diff --git a/doc/src/declarative/components.qdoc b/doc/src/declarative/components.qdoc index 9a6f2dd..db59b61 100644 --- a/doc/src/declarative/components.qdoc +++ b/doc/src/declarative/components.qdoc @@ -23,10 +23,18 @@ This example describes how to create a component from an existing snippet of Qml Assume you have an existing UI with a single 'Save' button, defined as follows: \code - - - - +Image { + source: "pics/button-background.png" + Text { + text: "Save" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + MouseRegion { + anchors.fill: parent + onClick: { saveData() } + } +} \endcode For the next release, you plan to add 'Cancel' and 'Reset' buttons. Rather than copying and pasting the above markup, you can create a component: @@ -36,12 +44,20 @@ For the next release, you plan to add 'Cancel' and 'Reset' buttons. Rather than \o Make some minor changes to define the component's interface: \code - - - - - - +Image { + property string label + signal clicked + source: "pics/button-background.png" + Text { + text: parent.label + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + MouseRegion { + anchors.fill: parent + onClick: { parent.click.emit() } + } +} \endcode The \a label property and \a click signal that were added effectively become part of the 'public API' of the MyButton component. In a similar manner, the Text and MouseRegion elements become invisible to anyone using the component. Note that the Text element now binds in its data from \a label, and the MouseRegion emits a generic signal. @@ -49,11 +65,11 @@ The \a label property and \a click signal that were added effectively become par \o The component can now be used elsewhere as MyButton: \code - +MyButton { label: "Save"; onClicked: saveData() } ... - +MyButton { label: "Cancel"; onClicked: cancelData() } ... - +MyButton { label: "Reset"; onClicked: resetData() } \endcode \endlist diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc index 959bc6d..534b32b 100644 --- a/doc/src/declarative/cppitem.qdoc +++ b/doc/src/declarative/cppitem.qdoc @@ -76,7 +76,7 @@ For example: QML_DECLARE_TYPE(MyCircle); QML_DEFINE_TYPE(MyCircle,Circle); \endcode -would make the \e MyCircle class accessable though the \c tag in QML. +would make the \e MyCircle class accessable though the \c Circle type in QML. \section1 Creating a new 'Fx' item in C++ diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp index db390d2..24ae428 100644 --- a/src/declarative/fx/qfxflipable.cpp +++ b/src/declarative/fx/qfxflipable.cpp @@ -80,8 +80,8 @@ Flipable { endX: 20 endY: 40 } - front: Image { src: "front.png" } - back: Image { src: "back.png" } + front: Image { source: "front.png" } + back: Image { source: "back.png" } states: [ State { name: "back" diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 53c6137..838da30 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -203,8 +203,8 @@ QFxScaleGrid *QFxImage::scaleGrid() \qml Item { Image { source: "tile.png" } - Image { x: 80; width: 100; height: 100; src: "tile.png" } - Image { x: 190; width: 100; height: 100; tile: true; src: "tile.png" } + Image { x: 80; width: 100; height: 100; source: "tile.png" } + Image { x: 190; width: 100; height: 100; tile: true; source: "tile.png" } } \endqml \image declarative-image_tile.png diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 84dc484..ecc2d65 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -448,7 +448,7 @@ QFxItem::~QFxItem() This example scales an image about its center. \qml Image { - src: "myimage.png" + source: "myimage.png" transformOrigin: "Center" scale: 4 } diff --git a/src/declarative/fx/qfxparticles.cpp b/src/declarative/fx/qfxparticles.cpp index 45de1a3..0ac537a 100644 --- a/src/declarative/fx/qfxparticles.cpp +++ b/src/declarative/fx/qfxparticles.cpp @@ -251,7 +251,7 @@ Rect { y: 0 width: parent.width height: 30 - src: "star.png" + source: "star.png" lifeSpan: 5000 count: 50 angle: 70 @@ -543,7 +543,7 @@ Rect { y: 0 width: parent.width height: 30 - src: "star.png" + source: "star.png" lifeSpan: 5000 count: 50 angle: 70 @@ -560,7 +560,7 @@ Rect { x: 120 width: 1 height: 1 - src: "star.png" + source: "star.png" lifeSpan: 5000 count: 200 angle: 270 @@ -698,7 +698,7 @@ void QFxParticles::setCount(int cnt) \qml Particles { - src: "star.png" + source: "star.png" lifeSpan: 200 lifeSpanDeviation: 100 } @@ -735,7 +735,7 @@ void QFxParticles::setLifeSpan(int ls) \qml Particles { - src: "star.png" + source: "star.png" lifeSpan: 200 lifeSpanDeviation: 100 } @@ -813,7 +813,7 @@ void QFxParticles::setFadeOutDuration(int dur) \qml Particles { - src: "star.png" + source: "star.png" angle: 60 angleDeviation: 90 } @@ -848,7 +848,7 @@ void QFxParticles::setAngle(qreal angle) \qml Particles { - src: "star.png" + source: "star.png" angle: 60 angleDeviation: 90 } @@ -880,7 +880,7 @@ void QFxParticles::setAngleDeviation(qreal dev) \qml Particles { - src: "star.png" + source: "star.png" velocity: 50 velocityDeviation: 20 } @@ -915,7 +915,7 @@ void QFxParticles::setVelocity(qreal velocity) \qml Particles { - src: "star.png" + source: "star.png" velocity: 50 velocityDeviation: 20 } diff --git a/src/declarative/fx/qfxreflectionfilter.cpp b/src/declarative/fx/qfxreflectionfilter.cpp index a55f374..0bc01a7 100644 --- a/src/declarative/fx/qfxreflectionfilter.cpp +++ b/src/declarative/fx/qfxreflectionfilter.cpp @@ -72,23 +72,23 @@ public: \qml HorizontalLayout { Image { - src: "icon.png" + source: "icon.png" filter: Reflection { } } Image { - src: "icon.png" + source: "icon.png" filter: Reflection { offset: 1 } } Image { - src: "icon.png" + source: "icon.png" filter: Reflection { offset: 1; alpha: 0.5 } } Image { - src: "icon.png" + source: "icon.png" filter: Reflection { offset: 1; alpha: 0.5; height: 50 } } Image { - src: "icon.png" + source: "icon.png" filter: Reflection { offset: 1; alpha: 0.5; height: 50; scale: 0.5 } } } @@ -147,7 +147,7 @@ void QFxReflectionFilter::setAlpha(qreal a) \qml Image { id: myImage - src: "album.png" + source: "album.png" filter: Reflection { height: myImage.height * 0.5 } diff --git a/src/declarative/fx/qfxshadowfilter.cpp b/src/declarative/fx/qfxshadowfilter.cpp index 4d34f74..83c1b47 100644 --- a/src/declarative/fx/qfxshadowfilter.cpp +++ b/src/declarative/fx/qfxshadowfilter.cpp @@ -86,7 +86,7 @@ Rect { } Image { - src: "pics/qtlogo.png" + source: "pics/qtlogo.png" filter: Shadow { yOffset: 8 xOffset: 8 diff --git a/src/declarative/fx/qfxtransform.cpp b/src/declarative/fx/qfxtransform.cpp index 1fe02d1..71ca716 100644 --- a/src/declarative/fx/qfxtransform.cpp +++ b/src/declarative/fx/qfxtransform.cpp @@ -322,7 +322,7 @@ void QFxRotation3D::update() The following example translates the image to 10, 3. \qml Image { - src: "logo.png" + source: "logo.png" transform: [ Translation3D { axis.startX: 0 @@ -520,9 +520,9 @@ QMatrix4x4 QFxPerspective::transform() const HorizontalLayout { margin: 10 spacing: 10 - Image { src: "qt.png" } + Image { source: "qt.png" } Image { - src: "qt.png" + source: "qt.png" transform: Squish { x:0; y:0; width:60; height:60 topLeftX:0; topLeftY:0 @@ -532,7 +532,7 @@ QMatrix4x4 QFxPerspective::transform() const } } Image { - src: "qt.png" + source: "qt.png" transform: Squish { x:0; y:0; width:60; height:60 topLeftX:0; topLeftY:0 @@ -542,7 +542,7 @@ QMatrix4x4 QFxPerspective::transform() const } } Image { - src: "qt.png" + source: "qt.png" transform: Squish { x:0; y:0; width:60; height:60 topLeftX:0; topLeftY:10 @@ -552,7 +552,7 @@ QMatrix4x4 QFxPerspective::transform() const } } Image { - src: "qt.png" + source: "qt.png" transform: Squish { x:0; y:0; width:60; height:60 topLeftX:10; topLeftY:0 -- cgit v0.12