From 8cefc95e3d91cb16ef6a7b16c18ef1e23a3911a9 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 12:43:43 +1000 Subject: Add missing NOTIFY --- doc/src/declarative/qmlmodels.qdoc | 2 +- src/declarative/fx/qfxborderimage.cpp | 4 ++-- src/declarative/fx/qfxborderimage.h | 7 ++++--- src/declarative/fx/qfxgridview.cpp | 4 ++-- src/declarative/fx/qfxgridview.h | 7 ++++--- src/declarative/fx/qfxlistview.cpp | 1 + src/declarative/fx/qfxlistview.h | 5 +++-- src/declarative/fx/qfxpositioners.cpp | 1 + src/declarative/fx/qfxpositioners.h | 3 ++- 9 files changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc index eca81cd..d0a5464 100644 --- a/doc/src/declarative/qmlmodels.qdoc +++ b/doc/src/declarative/qmlmodels.qdoc @@ -63,7 +63,7 @@ There are a number of QML elements that operate using data models: \o ListView \o GridView \o PathView -\o \l {qml-repeater}{Repeater} +\o \l Repeater \endlist QML supports several types of data model, which may be provided by QML diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 6616912..8f98a11 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -273,7 +273,7 @@ void QFxBorderImage::setHorizontalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->horizontalTileMode) { d->horizontalTileMode = t; - emit tileModeChanged(); + emit horizontalTileModeChanged(); update(); } } @@ -289,7 +289,7 @@ void QFxBorderImage::setVerticalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->verticalTileMode) { d->verticalTileMode = t; - emit tileModeChanged(); + emit verticalTileModeChanged(); update(); } } diff --git a/src/declarative/fx/qfxborderimage.h b/src/declarative/fx/qfxborderimage.h index eae9bd1..5bc1067 100644 --- a/src/declarative/fx/qfxborderimage.h +++ b/src/declarative/fx/qfxborderimage.h @@ -59,8 +59,8 @@ class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase Q_ENUMS(TileMode) Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) - Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY tileModeChanged) - Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY tileModeChanged) + Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) + Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) public: QFxBorderImage(QFxItem *parent=0); @@ -80,7 +80,8 @@ public: void setSource(const QUrl &url); Q_SIGNALS: - void tileModeChanged(); + void horizontalTileModeChanged(); + void verticalTileModeChanged(); protected: QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index a8b27f4..2ed704e 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -1000,7 +1000,7 @@ void QFxGridView::setCellWidth(int cellWidth) if (cellWidth != d->cellWidth && cellWidth > 0) { d->cellWidth = qMax(1, cellWidth); d->updateGrid(); - emit cellSizeChanged(); + emit cellWidthChanged(); d->layout(); } } @@ -1017,7 +1017,7 @@ void QFxGridView::setCellHeight(int cellHeight) if (cellHeight != d->cellHeight && cellHeight > 0) { d->cellHeight = qMax(1, cellHeight); d->updateGrid(); - emit cellSizeChanged(); + emit cellHeightChanged(); d->layout(); } } diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 08a7565..7f30f03 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -67,8 +67,8 @@ class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable Q_PROPERTY(Flow flow READ flow WRITE setFlow) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) - Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellSizeChanged) - Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellSizeChanged) + Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged) + Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged) Q_CLASSINFO("DefaultProperty", "data") public: @@ -121,7 +121,8 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void currentIndexChanged(); - void cellSizeChanged(); + void cellWidthChanged(); + void cellHeightChanged(); protected: virtual void viewportMoved(); diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 1247021..aa8ccfd 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -1180,6 +1180,7 @@ void QFxListView::setOrientation(Qt::Orientation orientation) setViewportHeight(-1); d->clear(); refill(); + emit orientationChanged(); d->updateCurrent(d->currentIndex); } } diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 3cff422..5a83604 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(bool strictlyEnforceHighlightRange READ strictlyEnforceHighlightRange WRITE setStrictlyEnforceHighlightRange) Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) - Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged) @@ -106,7 +106,7 @@ public: bool strictlyEnforceHighlightRange() const; void setStrictlyEnforceHighlightRange(bool strict); - + qreal preferredHighlightBegin() const; void setPreferredHighlightBegin(qreal); @@ -144,6 +144,7 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void spacingChanged(); + void orientationChanged(); void currentIndexChanged(); void currentSectionChanged(); void sectionExpressionChanged(); diff --git a/src/declarative/fx/qfxpositioners.cpp b/src/declarative/fx/qfxpositioners.cpp index e4500aa..f8e7213 100644 --- a/src/declarative/fx/qfxpositioners.cpp +++ b/src/declarative/fx/qfxpositioners.cpp @@ -97,6 +97,7 @@ void QFxBasePositioner::setSpacing(int s) return; d->_spacing = s; prePositioning(); + emit spacingChanged(); } QmlTransition *QFxBasePositioner::move() const diff --git a/src/declarative/fx/qfxpositioners.h b/src/declarative/fx/qfxpositioners.h index 89a61d7..d62da08 100644 --- a/src/declarative/fx/qfxpositioners.h +++ b/src/declarative/fx/qfxpositioners.h @@ -59,7 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxBasePositioner : public QFxItem { Q_OBJECT - Q_PROPERTY(int spacing READ spacing WRITE setSpacing) + Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(QmlTransition *move READ move WRITE setMove) Q_PROPERTY(QmlTransition *add READ add WRITE setAdd) Q_PROPERTY(QmlTransition *remove READ remove WRITE setRemove) @@ -93,6 +93,7 @@ protected: Q_SIGNALS: void layoutItemChanged(); + void spacingChanged(); protected Q_SLOTS: virtual void doPositioning()=0; -- cgit v0.12 From 04511e3dbbcdf40489852babbf4753e0f744c26f Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 9 Oct 2009 14:25:22 +1000 Subject: Improve qdoc generated QML documentation. --- doc/src/declarative/elements.qdoc | 2 +- tools/qdoc3/config.h | 4 ++++ tools/qdoc3/cppcodemarker.cpp | 12 ++++++------ tools/qdoc3/doc.cpp | 4 ++++ tools/qdoc3/helpprojectwriter.cpp | 12 ++++++++++-- tools/qdoc3/node.cpp | 4 +++- tools/qdoc3/node.h | 2 ++ tools/qdoc3/test/qml.qdocconf | 5 ++++- 8 files changed, 34 insertions(+), 11 deletions(-) diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index cb30a6e..98c4ee1 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -40,7 +40,7 @@ ****************************************************************************/ /*! -\page elements.html +\page qmlelements.html \target elements \title QML Elements diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h index 07cdb59..725129a 100644 --- a/tools/qdoc3/config.h +++ b/tools/qdoc3/config.h @@ -162,6 +162,10 @@ class Config #define CONFIG_FILEEXTENSIONS "fileextensions" +#ifdef QDOC_QML +#define CONFIG_QMLONLY "qmlonly" +#endif + QT_END_NAMESPACE #endif diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index ed3d150..1062f9c 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -1109,15 +1109,15 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, if (qmlClassNode) { if (style == Summary) { FastSection qmlproperties(qmlClassNode, - "QML Properties", + "Properties", "property", "properties"); FastSection qmlsignals(qmlClassNode, - "QML Signals", + "Signals", "signal", "signals"); FastSection qmlmethods(qmlClassNode, - "QML Methods", + "Methods", "method", "methods"); @@ -1146,9 +1146,9 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, append(sections,qmlmethods); } else if (style == Detailed) { - FastSection qmlproperties(qmlClassNode,"QML Property Documentation"); - FastSection qmlsignals(qmlClassNode,"QML Signal Documentation"); - FastSection qmlmethods(qmlClassNode,"QML Method Documentation"); + FastSection qmlproperties(qmlClassNode, "Property Documentation"); + FastSection qmlsignals(qmlClassNode,"Signal Documentation"); + FastSection qmlmethods(qmlClassNode,"Method Documentation"); NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); while (c != qmlClassNode->childNodes().end()) { if ((*c)->subType() == Node::QmlPropertyGroup) { diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 748390f..f4931b8 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -2841,6 +2841,10 @@ void Doc::initialize(const Config& config) DocParser::sourceDirs = config.getStringList(CONFIG_SOURCEDIRS); DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION); +#ifdef QDOC_QML + QmlClassNode::qmlOnly = config.getBool(CONFIG_QMLONLY); +#endif + QStringMap reverseAliasMap; QSet commands = config.subVars(CONFIG_ALIAS); diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index 4973387..52f54c0 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -187,8 +187,16 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const details << node->parent()->name()+"::"+node->name(); } else if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); - details << fake->fullTitle(); - details << fake->fullTitle(); +#ifdef QDOC_QML + if (fake->subType() == Node::QmlClass) { + details << (QmlClassNode::qmlOnly ? fake->name() : fake->fullTitle()); + details << "QML." + fake->name(); + } else +#endif + { + details << fake->fullTitle(); + details << fake->fullTitle(); + } } else { details << node->name(); details << node->name(); diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index d547d20..42b73d9 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -1057,6 +1057,8 @@ bool TargetNode::isInnerNode() const } #ifdef QDOC_QML +bool QmlClassNode::qmlOnly = false; + /*! Constructor for the Qml class node. */ @@ -1065,7 +1067,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const ClassNode* cn) : FakeNode(parent, name, QmlClass), cnode(cn) { - setTitle("QML " + name + " Element Reference"); + setTitle((qmlOnly ? "" : "QML ") + name + " Element Reference"); } /*! diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index 09f38d2..dfe882c 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -364,6 +364,8 @@ class QmlClassNode : public FakeNode const ClassNode* classNode() const { return cnode; } virtual QString fileBase() const; + static bool qmlOnly; + private: const ClassNode* cnode; }; diff --git a/tools/qdoc3/test/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf index 3a7d76a..3b5d8dc 100644 --- a/tools/qdoc3/test/qml.qdocconf +++ b/tools/qdoc3/test/qml.qdocconf @@ -7,6 +7,7 @@ include(qt-defines.qdocconf) project = Qml description = Qml Reference Documentation url = http://doc.qtsoftware.com/4.6 +qmlonly = true edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ QtXmlPatterns QtTest @@ -72,6 +73,8 @@ HTML.postheader = "  " \ "\n" \ "
" \ "" \ - "Home" \ + "Home ·" \ + " " \ + "Elements" \ "
" -- cgit v0.12 From 0dc2fe6685323a8aa6bc0e79f908aa9f2dafe6f2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 14:51:40 +1000 Subject: Output file/line for script errors --- src/declarative/qml/qmlbinding.cpp | 4 +- src/declarative/qml/qmlbinding.h | 3 +- src/declarative/qml/qmlcompiler.cpp | 18 ++++++-- src/declarative/qml/qmlcontext.cpp | 20 +++------ src/declarative/qml/qmlcontext_p.h | 3 +- src/declarative/qml/qmlexpression.cpp | 48 ++++++++++++++-------- src/declarative/qml/qmlexpression.h | 4 +- src/declarative/qml/qmlexpression_p.h | 4 +- src/declarative/qml/qmlinstruction_p.h | 2 + src/declarative/qml/qmlparser_p.h | 2 + src/declarative/qml/qmlvme.cpp | 7 ++-- .../declarative/qmlecmascript/data/scriptErrors.js | 2 + .../qmlecmascript/data/scriptErrors.qml | 10 +++++ .../qmlecmascript/tst_qmlecmascript.cpp | 20 +++++++++ 14 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptErrors.js create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptErrors.qml diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 3a34f46..58ce02c 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -67,8 +67,8 @@ QmlBindingPrivate::QmlBindingPrivate() { } -QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) +QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent) +: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate) { setParent(parent); } diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index e3a297c..1c0ccf1 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -90,7 +90,8 @@ class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, Q_OBJECT public: QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0); - QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); + QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int, + QObject *parent); ~QmlBinding(); void setTarget(const QmlMetaProperty &); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 12e8101..5e6a8aa 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -833,6 +833,8 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction script; script.type = QmlInstruction::StoreScript; script.line = -1; // ### + script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii)); + script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii); script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); output->bytecode << script; } @@ -1054,6 +1056,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) { QString scriptCode; + QString sourceUrl; + int lineNumber = 1; if (script->properties.count() == 1 && script->properties.begin().key() == QByteArray("source")) { @@ -1066,8 +1070,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) source->values.at(0)->object || !source->values.at(0)->value.isString()) COMPILE_EXCEPTION(source, "Invalid Script source value"); - QString sourceUrl = - output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); + sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); for (int ii = 0; ii < unit->resources.count(); ++ii) { if (unit->resources.at(ii)->url == sourceUrl) { @@ -1079,10 +1082,14 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } else if (!script->properties.isEmpty()) { COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); } else if (script->defaultProperty) { + sourceUrl = output->url.toString(); + QmlParser::Location currentLocation; for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) { Value *v = script->defaultProperty->values.at(ii); + if (lineNumber == 1) + lineNumber = v->location.start.line; if (v->object || !v->value.isString()) COMPILE_EXCEPTION(v, "Invalid Script block"); @@ -1105,8 +1112,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } - if (!scriptCode.isEmpty()) + if (!scriptCode.isEmpty()) { obj->scriptBlocks.append(scriptCode); + obj->scriptBlocksFile.append(sourceUrl); + obj->scriptBlocksLineNumber.append(lineNumber); + } return true; } @@ -2322,7 +2332,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; - store.line = prop->location.end.line; + store.line = binding->location.start.line; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index f6795aa..3f61867 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -61,7 +61,8 @@ QmlContextPrivate::QmlContextPrivate() { } -void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) +void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, + const QString &fileName, int lineNumber) { if (!engine) return; @@ -78,21 +79,10 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); - QScriptValue val = scriptEngine->evaluate(script); + QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ - qWarning() << exception.property(QLatin1String("fileName")).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - - } else { - qmlInfo(scopeObject) << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + QmlExpressionPrivate::printException(scriptEngine); scriptEngine->popContext(); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index d18bfda..fe74e28 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -94,7 +94,8 @@ public: QScriptValue scriptValue; QList scripts; - void addScript(const QString &script, QObject *scope); + void addScript(const QString &script, QObject *scope, + const QString &fileName = QString(), int lineNumber = 1); QUrl url; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 23e1700..6a6ef5d 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -89,8 +89,11 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, - QObject *me) + QObject *me, const QUrl &url, int lineNumber) { + data->fileName = url.toString(); + data->line = lineNumber; + quint32 *exprData = (quint32 *)expr; Q_ASSERT(*exprData == BasicScriptEngineData || *exprData == PreTransformedQtScriptData); @@ -107,7 +110,8 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { - dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression)); + dd->programs[progIdx] = + new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } QmlContextPrivate *ctxtPriv = ctxt->d_func(); @@ -145,11 +149,12 @@ QmlExpression::QmlExpression() /*! \internal */ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me, + const QUrl &url, int lineNumber, QmlExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QmlExpression); - d->init(ctxt, expr, rc, me); + d->init(ctxt, expr, rc, me, url, lineNumber); } /*! @@ -251,6 +256,28 @@ QVariant QmlExpressionPrivate::evalSSE() return rv; } +void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine) +{ + if (scriptEngine->hasUncaughtException() && + scriptEngine->uncaughtException().isError()) { + + QString fileName; + int lineNumber = scriptEngine->uncaughtExceptionLineNumber(); + + QScriptValue exception = scriptEngine->uncaughtException(); + QLatin1String fileNameProp("fileName"); + + if (!exception.property(fileNameProp).toString().isEmpty()){ + fileName = exception.property(fileNameProp).toString(); + } else { + fileName = QLatin1String(""); + } + + qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": " + << qPrintable(exception.toString()); + } +} + QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -291,19 +318,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QScriptValue svalue = data->expressionFunction.call(); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - QLatin1String fileNameProp("fileName"); - if (!exception.property(fileNameProp).toString().isEmpty()){ - qWarning() << exception.property(fileNameProp).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - } else { - qWarning() << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + printException(scriptEngine); if (secondaryScope) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index c295a1c..b85e0a7 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -89,8 +89,8 @@ Q_SIGNALS: protected: QmlExpression(QmlContext *, const QString &, QObject *, QmlExpressionPrivate &dd); - QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, - QmlExpressionPrivate &dd); + QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &, + int, QmlExpressionPrivate &dd); private Q_SLOTS: void __q_notify(); diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 33016e6..d9bb27b 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -136,7 +136,7 @@ public: }; void init(QmlContext *, const QString &, QObject *); - void init(QmlContext *, void *, QmlRefCount *, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *, const QUrl &, int); QmlExpressionData *data; @@ -150,6 +150,8 @@ public: static QmlExpressionPrivate *get(QmlExpression *expr) { return static_cast(QObjectPrivate::get(expr)); } + + static void printException(QScriptEngine *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 1dcdace..0da40c3 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -240,6 +240,8 @@ public: } storeString; struct { int value; + int fileName; + int lineNumber; } storeScript; struct { int propertyIndex; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 16862eb..d05cc73 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -168,6 +168,8 @@ namespace QmlParser // Script blocks that were nested under this object QStringList scriptBlocks; + QStringList scriptBlocksFile; + QList scriptBlocksLineNumber; // The bytes to cast instances by to get to the QmlParserStatus // interface. -1 indicates the type doesn't support this interface. diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index e4eef64..a057f11 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -567,7 +567,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreScript: { QObject *target = stack.top(); - cp->addScript(primitives.at(instr.storeScript.value), target); + cp->addScript(primitives.at(instr.storeScript.value), target, + primitives.at(instr.storeScript.fileName), + instr.storeScript.lineNumber); } break; @@ -597,12 +599,11 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) break; - QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); bind->addToObject(target); - bind->setSourceLocation(comp->url, instr.line); } break; diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.js b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js new file mode 100644 index 0000000..1d7b357 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js @@ -0,0 +1,2 @@ +// Comment +a = 10 diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml new file mode 100644 index 0000000..3fb8ff7 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml @@ -0,0 +1,10 @@ +import Qt 4.6 + +Object { + Script { source: "scriptErrors.js" } + Script { function getValue() { a = 10; return 0; } } + + property int x: a.value + property int y: getValue(); +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index dde3bb7..673be35 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -61,6 +61,7 @@ private slots: void objectToString(); void selfDeletingBinding(); void extendedObjectPropertyLookup(); + void scriptErrors(); private: QmlEngine engine; @@ -724,6 +725,25 @@ void tst_qmlecmascript::extendedObjectPropertyLookup() QVERIFY(object != 0); } +/* +Test file/lineNumbers for binding/Script errors. +*/ +void tst_qmlecmascript::scriptErrors() +{ + QmlComponent component(&engine, TEST_FILE("scriptErrors.qml")); + QString url = component.url().toString(); + + QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\""; + QString warning2 = url + ":7: TypeError: Result of expression 'a' [undefined] is not an object."; + QString warning3 = url + ":5: Error: Invalid write to global property \"a\""; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + QObject *object = component.create(); + QVERIFY(object != 0); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From a6743af8705a93fb30e278dd634ff37597ddb627 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 15:40:03 +1000 Subject: Remove deprecated write to signal property support --- src/declarative/qml/qmlmetaproperty.cpp | 30 +----------------------------- src/declarative/qml/qmlmetaproperty_p.h | 2 -- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 302ce8c..a43f6c3 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -698,30 +698,6 @@ QVariant QmlMetaProperty::read() const return QVariant(); } -void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) -{ - QString expr = value.toString(); - const QObjectList &children = object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == core.coreIndex) { - if (expr.isEmpty()) { - sig->disconnect(); - sig->deleteLater(); - } else { - sig->expression()->setExpression(expr); - } - return; - } - } - - if (!expr.isEmpty()) { - // XXX scope - (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object); - } -} - QVariant QmlMetaPropertyPrivate::readValueProperty() { uint type = q->type(); @@ -963,11 +939,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const if (!d->object) return; - if (type() & SignalProperty) { - - d->writeSignalProperty(value); - - } else if (d->core.isValid()) { + if (type() & Property && d->core.isValid()) { d->writeValueProperty(value, source); diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 00b9c3a..4576b71 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -96,8 +96,6 @@ public: int propertyType() const; QmlMetaProperty::PropertyCategory propertyCategory() const; - void writeSignalProperty(const QVariant &); - QVariant readValueProperty(); void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); -- cgit v0.12 From 89a5a33d5643eb31bb44adce8a8fd65986d76c20 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 15:56:36 +1000 Subject: Fixes yahoonews.qml Task-number: QT-2281 --- examples/declarative/xmldata/yahoonews.qml | 146 ++++++++++++----------------- 1 file changed, 60 insertions(+), 86 deletions(-) diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml index 6d43f46..7d8b8a2 100644 --- a/examples/declarative/xmldata/yahoonews.qml +++ b/examples/declarative/xmldata/yahoonews.qml @@ -5,100 +5,74 @@ Rectangle { GradientStop { position: 0; color: "black" } GradientStop { position: 1.0; color: "#AAAAAA" } } - width: 600 - height: 600 - resources: [ - XmlListModel { - id: feedModel - source: "http://rss.news.yahoo.com/rss/oceania" - query: "/rss/channel/item" - XmlRole { - name: "title" - query: "title/string()" - } - XmlRole { - name: "link" - query: "link/string()" - } - XmlRole { - name: "description" - query: "description/string()" + width: 600; height: 600 + + XmlListModel { + id: feedModel + source: "http://rss.news.yahoo.com/rss/oceania" + query: "/rss/channel/item" + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "link"; query: "link/string()" } + XmlRole { name: "description"; query: "description/string()" } + } + + Component { + id: feedDelegate + Item { + id: delegate + height: wrapper.height + 10 + + MouseRegion { + anchors.fill: wrapper + onPressed: delegate.ListView.view.currentIndex = index; + onClicked: if (wrapper.state == 'Details') wrapper.state = ''; else wrapper.state = 'Details'; } - }, - Component { - id: feedDelegate - Item { - id: delegate - height: wrapper.height + 10 - MouseRegion { - anchors.fill: wrapper - onPressed: { delegate.ListView.view.currentIndex = index; } - onClicked: { if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';} } + + Rectangle { + id: wrapper + y: 5; height: titleText.height + 10; width: 580 + color: "#F0F0F0"; radius: 5 + Text { + id: titleText + x: 10; y: 5 + text: '' + title + '' + font.bold: true; font.family: "Helvetica"; font.pointSize: 14 + onLinkActivated: { print('link clicked: ' + link) } } - Rectangle { - id: wrapper - y: 5 - height: titleText.height + 10 - width: 580 - color: "#F0F0F0" - radius: 5 - Text { - x: 10 - y: 5 - id: titleText - text: '' + title + '' - font.bold: true - font.family: "Helvetica" - font.pointSize: 14 - onLinkActivated: { print('link clicked: ' + link) } - } - Text { - x: 10 - id: description - text: description - width: 560 - wrap: true - font.family: "Helvetica" - anchors.top: titleText.bottom - anchors.topMargin: 5 - opacity: 0 + + Text { + x: 10 + id: descriptionText + text: description + width: 560 + wrap: true + font.family: "Helvetica" + anchors.top: titleText.bottom + anchors.topMargin: 5 + opacity: 0 + } + + states: State { + name: "Details" + PropertyChanges { target: wrapper; height: childrenRect.height + 10 } + PropertyChanges { target: descriptionText; opacity: 1 } + } + + transitions: Transition { + from: "*"; to: "Details"; reversible: true + SequentialAnimation { + NumberAnimation { duration: 200; properties: "height"; easing: "easeOutQuad" } + NumberAnimation { duration: 200; properties: "opacity" } } - states: [ - State { - name: "Details" - PropertyChanges { target: wrapper; height: childrenRect.height + 10 } - PropertyChanges { target: description; opacity: 1 } - } - ] - transitions: [ - Transition { - from: "*" - to: "Details" - reversible: true - SequentialAnimation { - NumberAnimation { - duration: 200 - properties: "height" - easing: "easeOutQuad" - } - NumberAnimation { - duration: 200 - properties: "opacity" - } - } - } - ] } } } - ] + } + ListView { id: list - x: 10 - y: 10 - width: parent.width - 20 - height: parent.height - 20 - clip: true + x: 10; y: 10 + width: parent.width - 20; height: parent.height - 20 model: feedModel delegate: feedDelegate } -- cgit v0.12 From e20dabec726b44cbe4e3078699932c59979cb977 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 16:42:14 +1000 Subject: Tweak scope ordering (again) ids and methods shadow properties. The reasoning is that the user explicitly declared these names, whereas they might not even know a property by that name exists. --- src/declarative/qml/qmlcontext.cpp | 11 ++--- src/declarative/qml/qmlcontext_p.h | 2 - src/declarative/qml/qmlcontextscriptclass.cpp | 57 +++++++++++++++------- src/declarative/qml/qmlcontextscriptclass_p.h | 6 ++- src/declarative/qml/qmlexpression.cpp | 10 +--- .../declarative/qmlecmascript/data/scope.2.qml | 42 ++++++++++++++++ .../qmlecmascript/tst_qmlecmascript.cpp | 41 +++++++++++----- 7 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/scope.2.qml diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 3f61867..43a4741 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -64,6 +64,8 @@ QmlContextPrivate::QmlContextPrivate() void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, const QString &fileName, int lineNumber) { + Q_Q(QmlContext); + if (!engine) return; @@ -71,11 +73,8 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(scriptValue); + scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - if (scopeObject) - scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); - QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); @@ -129,10 +128,6 @@ void QmlContextPrivate::init() if (parent) parent->d_func()->childContexts.insert(q); - - //set scope chain - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index fe74e28..9a77e94 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -91,8 +91,6 @@ public: QObjectList defaultObjects; int highPriorityCount; - QScriptValue scriptValue; - QList scripts; void addScript(const QString &script, QObject *scope, const QString &fileName = QString(), int lineNumber = 1); diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 6d2c58c..939d008 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -47,8 +47,9 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { - ContextData(QmlContext *c) : context(c) {} + ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {} QGuard context; + QGuard scopeObject; }; /* @@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass() { } -QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) @@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) return data->context; } -#include QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastScopeObject = 0; lastContext = 0; lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; QmlContext *bindContext = ((ContextData *)object)->context.data(); + QObject *scopeObject = ((ContextData *)object)->scopeObject.data(); if (!bindContext) return 0; while (bindContext) { - QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + QScriptClass::QueryFlags rv = + queryProperty(bindContext, scopeObject, name, flags); + scopeObject = 0; // Only applies to the first context if (rv) return rv; bindContext = bindContext->parentContext(); } @@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, +QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject, + const Identifier &name, QScriptClass::QueryFlags flags) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) { + lastContext = bindContext; + return QScriptClass::HandlesReadAccess; + } + } + + if (scopeObject) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(scopeObject, name, flags, 0); + if (rv) { + lastScopeObject = scopeObject; + lastContext = bindContext; + return rv; + } + } + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); @@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } return 0; } @@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + if (lastScopeObject) { - if (lastData) { + return ep->objectClass->property(lastScopeObject, name); + + } else if (lastData) { if (lastData->type) return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); @@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - Q_ASSERT(lastDefaultObject != -1); + Q_ASSERT(lastScopeObject || lastDefaultObject != -1); QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); @@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + if (lastScopeObject) { + ep->objectClass->setProperty(lastScopeObject, name, value); + } else { + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 761a115..126c8fe 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -67,7 +67,7 @@ public: QmlContextScriptClass(QmlEngine *); ~QmlContextScriptClass(); - QScriptValue newContext(QmlContext *); + QScriptValue newContext(QmlContext *, QObject * = 0); QmlContext *contextFromValue(const QScriptValue &); @@ -78,11 +78,13 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject, + const Identifier &, QScriptClass::QueryFlags flags); QmlEngine *engine; + QObject *lastScopeObject; QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 6a6ef5d..0de64d9 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -114,11 +114,8 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } - QmlContextPrivate *ctxtPriv = ctxt->d_func(); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); @@ -297,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - - if (data->me) - scriptContext->pushScope(ep->objectClass->newQObject(data->me)); + scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me)); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, diff --git a/tests/auto/declarative/qmlecmascript/data/scope.2.qml b/tests/auto/declarative/qmlecmascript/data/scope.2.qml new file mode 100644 index 0000000..433a22e --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scope.2.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Item { + property int a: 0 + property int b: 0 + + Script { + function b() { return 11; } + function c() { return 33; } + } + + Object { + id: a + property int value: 19 + } + + Object { + id: c + property int value: 24 + } + + Object { + id: nested + property int a: 1 + property int test: a.value + property int test2: b() + property int test3: c.value + } + + + // id takes precedence over local, and root properties + property int test1: a.value + property alias test2: nested.test + + // methods takes precedence over local, and root properties + property int test3: b() + property alias test4: nested.test2 + + // id takes precedence over methods + property int test5: c.value + property alias test6: nested.test3 +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 673be35..5e04f7c 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -538,20 +538,35 @@ void tst_qmlecmascript::nonExistantAttachedObject() void tst_qmlecmascript::scope() { - QmlComponent component(&engine, TEST_FILE("scope.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + { + QmlComponent component(&engine, TEST_FILE("scope.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 1); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toString(), QString("1Test")); + QCOMPARE(object->property("test4").toString(), QString("2Test")); + QCOMPARE(object->property("test5").toInt(), 1); + QCOMPARE(object->property("test6").toInt(), 1); + QCOMPARE(object->property("test7").toInt(), 2); + QCOMPARE(object->property("test8").toInt(), 2); + QCOMPARE(object->property("test9").toInt(), 1); + QCOMPARE(object->property("test10").toInt(), 3); + } + + { + QmlComponent component(&engine, TEST_FILE("scope.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); - QCOMPARE(object->property("test1").toInt(), 1); - QCOMPARE(object->property("test2").toInt(), 2); - QCOMPARE(object->property("test3").toString(), QString("1Test")); - QCOMPARE(object->property("test4").toString(), QString("2Test")); - QCOMPARE(object->property("test5").toInt(), 1); - QCOMPARE(object->property("test6").toInt(), 1); - QCOMPARE(object->property("test7").toInt(), 2); - QCOMPARE(object->property("test8").toInt(), 2); - QCOMPARE(object->property("test9").toInt(), 1); - QCOMPARE(object->property("test10").toInt(), 3); + QCOMPARE(object->property("test1").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 19); + QCOMPARE(object->property("test3").toInt(), 11); + QCOMPARE(object->property("test4").toInt(), 11); + QCOMPARE(object->property("test5").toInt(), 24); + QCOMPARE(object->property("test6").toInt(), 24); + } } /* -- cgit v0.12 From 8a88e6cf15636b0adaf5547e5fa883e9631ae1cb Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 16:49:06 +1000 Subject: fixes gridview.qml Task-number: QT-2271 --- examples/declarative/gridview/gridview.qml | 52 +++++++++--------------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/examples/declarative/gridview/gridview.qml b/examples/declarative/gridview/gridview.qml index 2e5110a..93931c7 100644 --- a/examples/declarative/gridview/gridview.qml +++ b/examples/declarative/gridview/gridview.qml @@ -4,57 +4,35 @@ Rectangle { width: 300; height: 400; color: "white" ListModel { - id: AppModel - ListElement { - name: "Music" - icon: "AudioPlayer_48.png" - } - ListElement { - name: "Movies" - icon: "VideoPlayer_48.png" - } - ListElement { - name: "Camera" - icon: "Camera_48.png" - } - ListElement { - name: "Calendar" - icon: "DateBook_48.png" - } - ListElement { - name: "Messaging" - icon: "EMail_48.png" - } - ListElement { - name: "Todo List" - icon: "TodoList_48.png" - } - ListElement { - name: "Contacts" - icon: "AddressBook_48.png" - } + id: appModel + ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" } + ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" } + ListElement { name: "Camera"; icon: "pics/Camera_48.png" } + ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" } + ListElement { name: "Messaging"; icon: "pics/EMail_48.png" } + ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" } + ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" } } Component { - id: AppDelegate + id: appDelegate Item { width: 100; height: 100 - Image { id: Icon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon } - Text { anchors.top: Icon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name } + Image { id: myIcon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon } + Text { anchors.top: myIcon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name } } } Component { - id: AppHighlight - Rectangle { width: 80; height: 80; color: "#FFFF88" } + id: appHighlight + Rectangle { width: 80; height: 80; color: "lightsteelblue" } } GridView { - id: List1 anchors.fill: parent cellWidth: 100; cellHeight: 100 - model: AppModel; delegate: AppDelegate - highlight: AppHighlight + model: appModel; delegate: appDelegate + highlight: appHighlight focus: true } } -- cgit v0.12 From c1e591809975119d87d3f2d7fdb33eda22f0ccd1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 17:02:04 +1000 Subject: Fix snow demo --- examples/declarative/snow/ImageBatch.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/declarative/snow/ImageBatch.qml b/examples/declarative/snow/ImageBatch.qml index 62f986c..86e11f7 100644 --- a/examples/declarative/snow/ImageBatch.qml +++ b/examples/declarative/snow/ImageBatch.qml @@ -35,14 +35,14 @@ GridView { XmlRole { name: "url"; query: "media:content/@url/string()" } } - Item { + delegate: Item { id: root property bool isSelected: GridView.isCurrentItem && grid.isSelected transformOrigin: "Center" width: grid.imageWidth; height: grid.imageHeight; Image { id: flickrImage; source: url; fillMode: "PreserveAspectFit"; smooth: true; anchors.fill: parent; - opacity: (status == 1)?1:0; opacity: Behavior { NumberAnimation { properties: "opacity" } } } + opacity: (status == Image.Ready)?1:0; /*opacity: Behavior { NumberAnimation { properties: "opacity" } }*/ } Loading { anchors.centerIn: parent; visible: flickrImage.status!=1 } states: State { -- cgit v0.12 From 165785ed7ad463100e144467a09708742259836c Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 17:08:03 +1000 Subject: Do not use 'resources:' in examples --- examples/declarative/listview/recipes.qml | 228 ++++++++++++------------ examples/declarative/webview/newwindows.qml | 33 ++-- examples/declarative/xmldata/daringfireball.qml | 81 ++++----- 3 files changed, 168 insertions(+), 174 deletions(-) diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml index 4ccb344..3410f56 100644 --- a/examples/declarative/listview/recipes.qml +++ b/examples/declarative/listview/recipes.qml @@ -1,128 +1,136 @@ import Qt 4.6 - import "content" + // This example illustrates expanding a list item to show a more detailed view + Rectangle { id: page width: 400; height: 240; color: "black" - resources: [ - // Delegate for the recipes. This delegate has two modes: - // 1. the list mode (default), which just shows the picture and title of the recipe. - // 2. the details mode, which also shows the ingredients and method. - Component { - id: recipeDelegate - Item { - id: wrapper - width: list.width - // Create a property to contain the visibility of the details. - // We can bind multiple element's opacity to this one property, - // rather than having a "PropertyChanges" line for each element we - // want to fade. - property real detailsOpacity : 0 - - // A simple rounded rectangle for the background - Rectangle { - id: background - x: 1; y: 2; width: parent.width-2; height: parent.height-4 - color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5 - } - // This mouse region covers the entire delegate. - // When clicked it changes mode to 'Details'. If we are already - // in Details mode, then no change will happen. - MouseRegion { - id: pageMouse - anchors.fill: parent - onClicked: { wrapper.state = 'Details' } - } - // Layout the page. Picture, title and ingredients at the top, method at the - // bottom. Note that elements that should not be visible in the list - // mode have their opacity set to wrapper.detailsOpacity. - Row { - id: topLayout - x: 10; y: 10; height: recipePic.height; width: parent.width - spacing: 10 - Image { - id: recipePic - source: picture; width: 48; height: 48 - } - Column { - height: recipePic.height; width: background.width-recipePic.width-20 - spacing: 5 - Text { id: name; text: title; font.bold: true; font.pointSize: 16 } - Text { - text: "Ingredients"; font.pointSize: 12; font.bold: true - opacity: wrapper.detailsOpacity - } - Text { - text: ingredients; wrap: true; width: parent.width - opacity: wrapper.detailsOpacity - } - } + + // Delegate for the recipes. This delegate has two modes: + // 1. the list mode (default), which just shows the picture and title of the recipe. + // 2. the details mode, which also shows the ingredients and method. + Component { + id: recipeDelegate + Item { + id: wrapper + width: list.width + + // Create a property to contain the visibility of the details. + // We can bind multiple element's opacity to this one property, + // rather than having a "PropertyChanges" line for each element we + // want to fade. + property real detailsOpacity : 0 + + // A simple rounded rectangle for the background + Rectangle { + id: background + x: 1; y: 2; width: parent.width - 2; height: parent.height - 4 + color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5 + } + + // This mouse region covers the entire delegate. + // When clicked it changes mode to 'Details'. If we are already + // in Details mode, then no change will happen. + MouseRegion { + id: pageMouse + anchors.fill: parent + onClicked: wrapper.state = 'Details'; + } + + // Layout the page. Picture, title and ingredients at the top, method at the + // bottom. Note that elements that should not be visible in the list + // mode have their opacity set to wrapper.detailsOpacity. + Row { + id: topLayout + x: 10; y: 10; height: recipePic.height; width: parent.width + spacing: 10 + + Image { + id: recipePic + source: picture; width: 48; height: 48 } - Item { - id: details - x: 10; width: parent.width-20 - anchors.top: topLayout.bottom; anchors.topMargin: 10 - anchors.bottom: parent.bottom; anchors.bottomMargin: 10 - opacity: wrapper.detailsOpacity + + Column { + height: recipePic.height; width: background.width-recipePic.width-20 + spacing: 5 + Text { id: name; text: title; font.bold: true; font.pointSize: 16 } Text { - id: methodTitle - text: "Method"; font.pointSize: 12; font.bold: true - anchors.top: parent.top - } - Flickable { - id: flick - anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom - width: parent.width; viewportHeight: methodText.height; clip: true - Text { id: methodText; text: method; wrap: true; width: details.width } - } - Image { - anchors.right: flick.right; anchors.top: flick.top - source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1 + text: "Ingredients"; font.pointSize: 12; font.bold: true + opacity: wrapper.detailsOpacity } - Image { - anchors.right: flick.right; anchors.bottom: flick.bottom - source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1 + Text { + text: ingredients; wrap: true; width: parent.width + opacity: wrapper.detailsOpacity } } - // A button to close the detailed view, i.e. set the state back to default (''). - MediaButton { - anchors.right: background.right; anchors.rightMargin: 5 - y: 10; opacity: wrapper.detailsOpacity - text: "Close"; onClicked: { wrapper.state = '' } + } + + Item { + id: details + x: 10; width: parent.width-20 + anchors.top: topLayout.bottom; anchors.topMargin: 10 + anchors.bottom: parent.bottom; anchors.bottomMargin: 10 + opacity: wrapper.detailsOpacity + + Text { + id: methodTitle + text: "Method"; font.pointSize: 12; font.bold: true + anchors.top: parent.top + } + Flickable { + id: flick + anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom + width: parent.width; viewportHeight: methodText.height; clip: true + Text { id: methodText; text: method; wrap: true; width: details.width } } - // Make the default height equal the hight of the picture, plus margin. - height: 68 - states: [ - State { - name: "Details" - PropertyChanges { target: background; color: "white" } - // Make the picture bigger - PropertyChanges { target: recipePic; width: 128; height: 128 } - // Make details visible - PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 } - // Make the detailed view fill the entire list area - PropertyChanges { target: wrapper; height: list.height } - // Move the list so that this item is at the top. - PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y } - // Disallow flicking while we're in detailed view - PropertyChanges { target: wrapper.ListView.view; interactive: false } - } - ] - transitions: [ - Transition { - // Make the state changes smooth - ParallelAnimation { - ColorAnimation { property: "color"; duration: 500 } - NumberAnimation { - duration: 300; properties: "detailsOpacity,x,viewportY,height,width" - } - } + Image { + anchors.right: flick.right; anchors.top: flick.top + source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1 + } + Image { + anchors.right: flick.right; anchors.bottom: flick.bottom + source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1 + } + } + + // A button to close the detailed view, i.e. set the state back to default (''). + MediaButton { + anchors.right: background.right; anchors.rightMargin: 5 + y: 10; opacity: wrapper.detailsOpacity + text: "Close"; onClicked: wrapper.state = ''; + } + + // Make the default height equal the hight of the picture, plus margin. + height: 68 + + states: State { + name: "Details" + PropertyChanges { target: background; color: "white" } + // Make the picture bigger + PropertyChanges { target: recipePic; width: 128; height: 128 } + // Make details visible + PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 } + // Make the detailed view fill the entire list area + PropertyChanges { target: wrapper; height: list.height } + // Move the list so that this item is at the top. + PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y } + // Disallow flicking while we're in detailed view + PropertyChanges { target: wrapper.ListView.view; interactive: false } + } + + transitions: Transition { + // Make the state changes smooth + ParallelAnimation { + ColorAnimation { property: "color"; duration: 500 } + NumberAnimation { + duration: 300; properties: "detailsOpacity,x,viewportY,height,width" } - ] + } } } - ] + } + // The actual list ListView { id: list diff --git a/examples/declarative/webview/newwindows.qml b/examples/declarative/webview/newwindows.qml index 59e3b3e..e2ed58f 100644 --- a/examples/declarative/webview/newwindows.qml +++ b/examples/declarative/webview/newwindows.qml @@ -7,22 +7,23 @@ import Qt 4.6 Row { id: pages - height: 200 - resources: [ - Component { - id: webViewPage - Rectangle { - width: webView.width - height: webView.height - WebView { - id: webView - newWindowComponent: webViewPage - newWindowParent: pages - url: "newwindows.html" - } - } + height: 200; width: 500 + + Component { + id: webViewPage + Rectangle { + width: webView.width + height: webView.height + border.color: "gray" + + WebView { + id: webView + newWindowComponent: webViewPage + newWindowParent: pages + url: "newwindows.html" + } } - ] - width: 500 + } + Loader { sourceComponent: webViewPage } } diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml index bea38c8..938bdd5 100644 --- a/examples/declarative/xmldata/daringfireball.qml +++ b/examples/declarative/xmldata/daringfireball.qml @@ -2,59 +2,44 @@ import Qt 4.6 Rectangle { color: "white" - width: 600 - height: 600 - resources: [ - XmlListModel { - id: feedModel - source: "http://daringfireball.net/index.xml" - query: "/feed/entry" - namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" - XmlRole { - name: "title" - query: "title/string()" - } - XmlRole { - name: "tagline" - query: "author/name/string()" + width: 600; height: 600 + + XmlListModel { + id: feedModel + source: "http://daringfireball.net/index.xml" + query: "/feed/entry" + namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "tagline"; query: "author/name/string()" } + XmlRole { name: "content"; query: "content/string()" } + } + + Component { + id: feedDelegate + Item { + height: childrenRect.height + 20 + Text { + id: titleText + x: 10 + text: title; font.bold: true } - XmlRole { - name: "content" - query: "content/string()" + Text { + text: 'by ' + tagline + anchors.left: titleText.right; anchors.leftMargin: 10 + font.italic: true } - }, - Component { - id: feedDelegate - Item { - height: childrenRect.height + 20 - Text { - x: 10 - id: titleText - text: title - font.bold: true - } - Text { - text: 'by ' + tagline - anchors.left: titleText.right - anchors.leftMargin: 10 - font.italic: true - } - Text { - x: 10 - text: content - anchors.top: titleText.bottom - width: 580 - wrap: true - onLinkActivated: { print('link clicked: ' + link) } - } + Text { + x: 10 + text: content + anchors.top: titleText.bottom + width: 580; wrap: true + onLinkActivated: { print('link clicked: ' + link) } } } - ] + } + ListView { - id: list anchors.fill: parent - clip: true - model: feedModel - delegate: feedDelegate + model: feedModel; delegate: feedDelegate } } -- cgit v0.12 From 3b3213679a35cdfb1eedcd5b27e6c40f1eca45fd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 18:32:30 +1000 Subject: Support aliases to enum properties --- src/declarative/qml/qmlcompiler.cpp | 7 +++++-- tests/auto/declarative/qmllanguage/data/Alias2.qml | 9 +++++++++ tests/auto/declarative/qmllanguage/data/alias.4.qml | 6 ++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 9 +++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/Alias2.qml create mode 100644 tests/auto/declarative/qmllanguage/data/alias.4.qml diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 5e6a8aa..8856892 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2253,10 +2253,13 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); + const char *typeName = aliasProperty.typeName(); + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, aliasProperty.typeName(), - builder.methodCount() - 1); + builder.addProperty(prop.name, typeName, builder.methodCount() - 1); propBuilder.setScriptable(true); return true; } diff --git a/tests/auto/declarative/qmllanguage/data/Alias2.qml b/tests/auto/declarative/qmllanguage/data/Alias2.qml new file mode 100644 index 0000000..b7e81a5 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/Alias2.qml @@ -0,0 +1,9 @@ +import Test 1.0 +import Qt 4.6 + +Object { + property var other + other: MyTypeObject { id: obj } + property alias enumAlias: obj.enumProperty; +} + diff --git a/tests/auto/declarative/qmllanguage/data/alias.4.qml b/tests/auto/declarative/qmllanguage/data/alias.4.qml new file mode 100644 index 0000000..bd6a769 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/alias.4.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +Alias2 { + enumAlias: MyTypeObject.EnumVal2 +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 3825b62..135a207 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -612,6 +612,15 @@ void tst_qmllanguage::aliasProperties() delete object; } + // Enum aliases + { + QmlComponent component(&engine, TEST_FILE("alias.4.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("enumAlias").toInt(), 1); + } } class TestType : public QObject { -- cgit v0.12 From 76448b41bb9c6212d2534f0597f9973c881c77bd Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 9 Oct 2009 12:11:15 +0200 Subject: Fix build --- src/declarative/qml/qmlpropertycache_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index f1b1219..91b0c53 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -132,7 +132,7 @@ QmlPropertyCache::Data::Data() { } -bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other) +bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other) { return flags == other.flags && propType == other.propType && -- cgit v0.12 From a700d7c263748d3635eb06a7091164fd75ec608c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 20:17:04 +1000 Subject: Add id aliases --- doc/src/declarative/extending.qdoc | 6 ++-- src/declarative/qml/qmlcompiler.cpp | 33 +++++++++++++++------- src/declarative/qml/qmlvmemetaobject.cpp | 26 ++++++++++++----- .../auto/declarative/qmllanguage/data/alias.5.qml | 13 +++++++++ .../declarative/qmllanguage/tst_qmllanguage.cpp | 24 ++++++++++++++++ 5 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/alias.5.qml diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 649eab1..bc18108 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -645,13 +645,13 @@ value, a property alias includes a compulsary alias reference. The alias reference is used to locate the aliased property. While similar to a property binding, the alias reference syntax is highly restricted. -An alias reference takes the form +An alias reference takes one of the following forms \code . + \endcode where must refer to an object id within the same component as the type -declaring the alias, and refers to a property on this object. The -alias reference syntax may become more flexibly in future releases. +declaring the alias, and, optionally, refers to a property on that object. Here is the property definition example rewritten to use property aliases. \code diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 8856892..d36b1c9 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2236,31 +2236,44 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, QStringList alias = astNodeToStringList(node); - if (alias.count() != 2) + if (alias.count() != 1 && alias.count() != 2) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); if (!compileState.ids.contains(alias.at(0))) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); Object *idObject = compileState.ids[alias.at(0)]; - int propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); - if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + QByteArray typeName; + + int propIdx = -1; + bool writable = false; + if (alias.count() == 2) { + propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + + if (-1 == propIdx) + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + + QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + writable = aliasProperty.isWritable(); - QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + else + typeName = aliasProperty.typeName(); + } else { + typeName = idObject->metaObject()->className(); + typeName += "*"; + } data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); - const char *typeName = aliasProperty.typeName(); - if (aliasProperty.isEnumType()) - typeName = "int"; // Avoid introducing a dependency on the aliased metaobject - builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, typeName, builder.methodCount() - 1); + builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); propBuilder.setScriptable(true); + propBuilder.setWritable(writable); return true; } diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index f473743..a324795 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -181,20 +181,32 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) (QmlContextPrivate *)QObjectPrivate::get(ctxt); QObject *target = ctxtPriv->idValues[d->contextIdx].data(); - if (!target) return -1; + if (!target) { + if (d->propertyIdx == -1) + *reinterpret_cast(a[0]) = target; + return -1; + } if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { int sigIdx = methodOffset + id + metaData->propertyCount; QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); - QMetaProperty prop = - target->metaObject()->property(d->propertyIdx); - if (prop.hasNotifySignal()) - QMetaObject::connect(target, prop.notifySignalIndex(), - object, sigIdx); + if (d->propertyIdx != -1) { + QMetaProperty prop = + target->metaObject()->property(d->propertyIdx); + if (prop.hasNotifySignal()) + QMetaObject::connect(target, prop.notifySignalIndex(), + object, sigIdx); + } aConnected.setBit(id); } - return QMetaObject::metacall(target, c, d->propertyIdx, a); + + if (d->propertyIdx == -1) { + *reinterpret_cast(a[0]) = target; + return -1; + } else { + return QMetaObject::metacall(target, c, d->propertyIdx, a); + } } return -1; diff --git a/tests/auto/declarative/qmllanguage/data/alias.5.qml b/tests/auto/declarative/qmllanguage/data/alias.5.qml new file mode 100644 index 0000000..39bfd9b --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/alias.5.qml @@ -0,0 +1,13 @@ +import Qt 4.6 +import Test 1.0 + +Object { + property alias otherAlias: otherObject + + property var other + other: MyQmlObject { + id: otherObject + value: 10 + } +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 135a207..ff78e6d 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -620,6 +620,30 @@ void tst_qmllanguage::aliasProperties() QVERIFY(object != 0); QCOMPARE(object->property("enumAlias").toInt(), 1); + + delete object; + } + + // Id aliases + { + QmlComponent component(&engine, TEST_FILE("alias.5.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVariant v = object->property("otherAlias"); + QCOMPARE(v.userType(), qMetaTypeId()); + MyQmlObject *o = qvariant_cast(v); + QCOMPARE(o->value(), 10); + + delete o; + + v = object->property("otherAlias"); + QCOMPARE(v.userType(), qMetaTypeId()); + o = qvariant_cast(v); + QVERIFY(o == 0); + + delete object; } } -- cgit v0.12 From ac507b4752dcd065038130d224910a6dc64f8f37 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 28 Sep 2009 10:38:30 +1000 Subject: Improve Behavior reliability. --- src/corelib/kernel/qmetaobject.cpp | 5 +- src/declarative/extra/qmlbehavior.cpp | 179 +++++------------------- src/declarative/extra/qmlbehavior.h | 22 +-- src/declarative/qml/qml.pri | 2 + src/declarative/qml/qmlbinding.cpp | 20 +-- src/declarative/qml/qmlbinding.h | 12 +- src/declarative/qml/qmlbindingoptimizations.cpp | 32 +++-- src/declarative/qml/qmlbindingoptimizations_p.h | 9 +- src/declarative/qml/qmlcompiler.cpp | 47 +++++-- src/declarative/qml/qmlcompiler_p.h | 3 +- src/declarative/qml/qmlcomponent.cpp | 2 +- src/declarative/qml/qmlinstruction.cpp | 3 + src/declarative/qml/qmlinstruction_p.h | 6 + src/declarative/qml/qmlmetaproperty.cpp | 86 ++++++++---- src/declarative/qml/qmlmetaproperty.h | 9 +- src/declarative/qml/qmlmetaproperty_p.h | 9 +- src/declarative/qml/qmlmetatype.cpp | 29 +++- src/declarative/qml/qmlmetatype.h | 14 +- src/declarative/qml/qmlparser.cpp | 3 + src/declarative/qml/qmlparser_p.h | 2 + src/declarative/qml/qmlvaluetype.cpp | 40 +++--- src/declarative/qml/qmlvaluetype_p.h | 19 +-- src/declarative/qml/qmlvaluetypescriptclass.cpp | 2 +- src/declarative/qml/qmlvme.cpp | 86 ++++++------ src/declarative/qml/qmlvmemetaobject.cpp | 27 ++++ src/declarative/qml/qmlvmemetaobject_p.h | 4 + src/declarative/util/qmlanimation.cpp | 24 ++-- src/declarative/util/qmltransitionmanager.cpp | 11 +- 28 files changed, 380 insertions(+), 327 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index f98c449..10eb955 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2237,7 +2237,10 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const // -1 (unchanged): normal qt_metacall, result stored in argv[0] // changed: result stored directly in value, return the value of status int status = -1; - void *argv[] = { 0, &v, &status }; + // the flags variable is used by the declarative module to implement + // interception of property writes. + int flags = 0; + void *argv[] = { 0, &v, &status, &flags }; if (t == QVariant::LastType) argv[0] = &v; else diff --git a/src/declarative/extra/qmlbehavior.cpp b/src/declarative/extra/qmlbehavior.cpp index 7784ef5..e30bd39 100644 --- a/src/declarative/extra/qmlbehavior.cpp +++ b/src/declarative/extra/qmlbehavior.cpp @@ -44,180 +44,77 @@ #include "qmltransition.h" #include "qmlbehavior.h" #include +#include #include QT_BEGIN_NAMESPACE QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Behavior,QmlBehavior) -class QmlBehaviorData : public QObject -{ -Q_OBJECT -public: - QmlBehaviorData(QObject *parent) - : QObject(parent) {} - - Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged) - Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged) - QVariant endValue() const { return e; } - QVariant startValue() const { return s; } - - QVariant e; - QVariant s; - -Q_SIGNALS: - void valuesChanged(); - -private: - friend class QmlBehavior; -}; - class QmlBehaviorPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlBehavior) public: - QmlBehaviorPrivate() : operations(this) {} + QmlBehaviorPrivate() : animation(0) {} + QmlMetaProperty property; QVariant currentValue; - - QVariant fromValue; - QVariant toValue; - class AnimationList : public QmlConcreteList - { - public: - AnimationList(QmlBehaviorPrivate *parent) : _parent(parent) {} - virtual void append(QmlAbstractAnimation *a) - { - QmlConcreteList::append(a); - _parent->group->addAnimation(a->qtAnimation()); - if (_parent->property.isValid()) { - a->setTarget(_parent->property); - } - } - virtual void clear() { QmlConcreteList::clear(); } //### - private: - QmlBehaviorPrivate *_parent; - }; - AnimationList operations; - QParallelAnimationGroup *group; + QmlAbstractAnimation *animation; }; -/*! - \qmlclass Behavior QmlBehavior - \brief The Behavior element allows you to specify a default animation for a property change. - - In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property: - \code - Rectangle { - width: 20; height: 20 - color: "#00ff00" - y: 200 //initial value - y: Behavior { - NumberAnimation { - easing: "easeOutBounce(amplitude:100)" - duration: 200 - } - } - } - \endcode -*/ - QmlBehavior::QmlBehavior(QObject *parent) -: QObject(*(new QmlBehaviorPrivate), parent) -{ - Q_D(QmlBehavior); - d->group = new QParallelAnimationGroup; - QFx_setParent_noEvent(d->group, this); -} - -/*! - \qmlproperty QVariant Behavior::from - This property holds a selector specifying a starting value for the behavior. - - If you only want the behavior to apply when the change starts at a - specific value you can specify fromValue. This selector is used in conjunction - with the to selector. -*/ - -QVariant QmlBehavior::fromValue() const + : QObject(*(new QmlBehaviorPrivate), parent) { - Q_D(const QmlBehavior); - return d->fromValue; } -void QmlBehavior::setFromValue(const QVariant &v) +QmlAbstractAnimation *QmlBehavior::animation() { Q_D(QmlBehavior); - d->fromValue = v; + return d->animation; } -/*! - \qmlproperty QVariant Behavior::to - This property holds a selector specifying a ending value for the behavior. - - If you only want the behavior to apply when the change ends at a - specific value you can specify toValue. This selector is used in conjunction - with the from selector. -*/ - -QVariant QmlBehavior::toValue() const -{ - Q_D(const QmlBehavior); - return d->toValue; -} - -void QmlBehavior::setToValue(const QVariant &v) +void QmlBehavior::setAnimation(QmlAbstractAnimation *animation) { Q_D(QmlBehavior); - d->toValue = v; -} + if (d->animation) { + qmlInfo(this) << "Can't change the animation assigned to a Behavior."; + return; + } -QmlList* QmlBehavior::operations() -{ - Q_D(QmlBehavior); - return &d->operations; + d->animation = animation; + if (d->animation) + d->animation->setTarget(d->property); } QmlBehavior::~QmlBehavior() { - //### do we need any other cleanup here? } -bool QmlBehavior::_ignore = false; -void QmlBehavior::propertyValueChanged() +void QmlBehavior::write(const QVariant &value) { Q_D(QmlBehavior); - if (_ignore) + if (!d->animation) { + d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); return; + } - QVariant newValue = d->property.read(); - - if ((!fromValue().isValid() || fromValue() == d->currentValue) && - (!toValue().isValid() || toValue() == newValue)) { - - //### does this clean up everything needed? - d->group->stop(); - - QmlStateOperation::ActionList actions; - Action action; - action.property = d->property; - action.fromValue = d->currentValue; - action.toValue = newValue; - actions << action; + d->currentValue = d->property.read(); - _ignore = true; - d->property.write(d->currentValue); + d->animation->qtAnimation()->stop(); - QList after; - for (int ii = 0; ii < d->operations.count(); ++ii) { - d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward); - } - d->group->start(); - if (!after.contains(d->property)) - d->property.write(newValue); - _ignore = false; - } + QmlStateOperation::ActionList actions; + Action action; + action.property = d->property; + action.fromValue = d->currentValue; + action.toValue = value; + actions << action; - d->currentValue = newValue; + QList after; + if (d->animation) + d->animation->transition(actions, after, QmlAbstractAnimation::Forward); + d->animation->qtAnimation()->start(); + if (!after.contains(d->property)) + d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } void QmlBehavior::setTarget(const QmlMetaProperty &property) @@ -225,12 +122,8 @@ void QmlBehavior::setTarget(const QmlMetaProperty &property) Q_D(QmlBehavior); d->property = property; d->currentValue = property.read(); - d->property.connectNotifier(this, SLOT(propertyValueChanged())); - for (int ii = 0; ii < d->operations.count(); ++ii) { - d->operations.at(ii)->setTarget(property); - } + if (d->animation) + d->animation->setTarget(property); } QT_END_NAMESPACE - -#include "qmlbehavior.moc" diff --git a/src/declarative/extra/qmlbehavior.h b/src/declarative/extra/qmlbehavior.h index a4a0679..994d85c 100644 --- a/src/declarative/extra/qmlbehavior.h +++ b/src/declarative/extra/qmlbehavior.h @@ -43,6 +43,7 @@ #define QMLBEHAVIOR_H #include +#include #include #include @@ -54,32 +55,23 @@ QT_MODULE(Declarative) class QmlAbstractAnimation; class QmlBehaviorPrivate; -class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueSource +class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueInterceptor { Q_OBJECT Q_DECLARE_PRIVATE(QmlBehavior) - Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue) - Q_PROPERTY(QVariant to READ toValue WRITE setToValue) - Q_CLASSINFO("DefaultProperty", "operations") - Q_PROPERTY(QmlList* operations READ operations) + Q_CLASSINFO("DefaultProperty", "animation") + Q_PROPERTY(QmlAbstractAnimation *animation READ animation WRITE setAnimation) public: QmlBehavior(QObject *parent=0); ~QmlBehavior(); - QVariant fromValue() const; - void setFromValue(const QVariant &); - QVariant toValue() const; - void setToValue(const QVariant &); virtual void setTarget(const QmlMetaProperty &); + virtual void write(const QVariant &value); - QmlList* operations(); - - static bool _ignore; - -private Q_SLOTS: - void propertyValueChanged(); + QmlAbstractAnimation *animation(); + void setAnimation(QmlAbstractAnimation *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index a2e2050..2e62a3b 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -10,6 +10,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlcontext.cpp \ qml/qmlcustomparser.cpp \ qml/qmlpropertyvaluesource.cpp \ + qml/qmlpropertyvalueinterceptor.cpp \ qml/qmlproxymetaobject.cpp \ qml/qmlvme.cpp \ qml/qmlcompiler.cpp \ @@ -59,6 +60,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcustomparser_p.h \ qml/qmlcustomparser_p_p.h \ qml/qmlpropertyvaluesource.h \ + qml/qmlpropertyvalueinterceptor.h \ qml/qmlboundsignal_p.h \ qml/qmlparserstatus.h \ qml/qmlproxymetaobject_p.h \ diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 3a34f46..907dcfa 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -97,7 +97,7 @@ QmlMetaProperty QmlBinding::property() const return d->bindingData()->property; } -void QmlBinding::update() +void QmlBinding::update(QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); @@ -119,17 +119,17 @@ void QmlBinding::update() int idx = data->property.coreIndex(); Q_ASSERT(idx != -1); - void *a[1]; + QmlBinding *t = this; - a[0] = (void *)&t; - QMetaObject::metacall(data->property.object(), + int status = -1; + void *a[] = { &t, 0, &status, &flags }; + QMetaObject::metacall(data->property.object(), QMetaObject::WriteProperty, idx, a); } else { - QVariant value = this->value(); - data->property.write(value, QmlMetaProperty::Binding); + data->property.write(value, flags); } data->updating = false; @@ -146,17 +146,17 @@ void QmlBinding::valueChanged() update(); } -void QmlBinding::setEnabled(bool e) +void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); d->bindingData()->enabled = e; setTrackChange(e); - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); if (e) { addToObject(d->bindingData()->property.object()); - update(); + update(flags); } else { removeFromObject(); } @@ -231,7 +231,7 @@ QString QmlAbstractBinding::expression() const return QLatin1String(""); } -void QmlAbstractBinding::setEnabled(bool e) +void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags) { if (e) m_mePtr = 0; } diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index e3a297c..bc5a42f 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -47,6 +47,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -62,10 +63,12 @@ public: virtual QString expression() const; - virtual void setEnabled(bool) = 0; + void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); } + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0; virtual int propertyIndex() = 0; - virtual void update() = 0; + void update() { update(QmlMetaProperty::DontRemoveBinding); } + virtual void update(QmlMetaProperty::WriteFlags) = 0; void addToObject(QObject *); void removeFromObject(); @@ -99,12 +102,13 @@ public: bool enabled() const; // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); virtual QString expression() const; public Q_SLOTS: - void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } protected: virtual void valueChanged(); diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index e4ca358..6dc221e 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -69,16 +69,16 @@ QmlBinding_Id::~QmlBinding_Id() removeFromContext(); } -void QmlBinding_Id::setEnabled(bool e) +void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_Id::propertyIndex() @@ -86,7 +86,7 @@ int QmlBinding_Id::propertyIndex() return m_propertyIdx; } -void QmlBinding_Id::update() +void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags) { QmlContextPrivate *ctxtPriv = static_cast(QObjectPrivate::get(context())); @@ -102,7 +102,8 @@ void QmlBinding_Id::update() } QObject *o = ctxtPriv->idValues[m_id].data(); - void *a[] = { &o, 0 }; + int status = -1; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -123,7 +124,9 @@ void QmlBinding_Id::reset() removeFromContext(); QObject *o = 0; - void *a[] = { &o, 0 }; + int status = -1; + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -150,17 +153,17 @@ QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx, { } -void QmlBinding_ObjProperty::setEnabled(bool e) +void QmlBinding_ObjProperty::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { m_enabled = e; if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_ObjProperty::propertyIndex() @@ -168,21 +171,24 @@ int QmlBinding_ObjProperty::propertyIndex() return m_propertyIdx; } -void QmlBinding_ObjProperty::update() +void QmlBinding_ObjProperty::update(QmlMetaProperty::WriteFlags flags) { if (!m_enabled) return; QObject *value = 0; - void *a[] = { &value, 0 }; + int status = -1; + void *ra[] = { &value, 0, &status }; // Read QMetaObject::metacall(m_context, QMetaObject::ReadProperty, - m_contextIdx, a); + m_contextIdx, ra); + + void *wa[] = { &value, 0, &status, &flags }; // Write QMetaObject::metacall(m_object, QMetaObject::WriteProperty, - m_propertyIdx, a); + m_propertyIdx, wa); // Connect notify if needed. Only need to connect once, so we set // m_notifyIdx back to -1 afterwards diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index 4862007..d0a4df4 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -69,9 +69,9 @@ public: virtual ~QmlBinding_Id(); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); - virtual void update(); + virtual void update(QmlMetaProperty::WriteFlags flags); void reset(); @@ -96,11 +96,12 @@ public: QObject *context, int contextIdx, int notifyIdx); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); private Q_SLOTS: - virtual void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } private: bool m_enabled; diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 12e8101..71f86d9 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1521,6 +1521,24 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop, store.assignValueSource.castValue = valueType->propertyValueSourceCast(); output->bytecode << store; + } else if (v->type == Value::ValueInterceptor) { + genObject(v->object); + + QmlInstruction store; + store.type = QmlInstruction::StoreValueInterceptor; + store.line = v->object->location.start.line; + if (valueTypeProperty) { + store.assignValueInterceptor.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index); + store.assignValueInterceptor.owner = 1; + } else { + store.assignValueInterceptor.property = + QmlMetaPropertyPrivate::saveProperty(prop->index); + store.assignValueInterceptor.owner = 0; + } + QmlType *valueType = QmlMetaType::qmlType(v->object->metatype); + store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast(); + output->bytecode << store; + } else if (v->type == Value::PropertyBinding) { genBindingAssignment(v, prop, obj, valueTypeProperty); @@ -1625,7 +1643,7 @@ bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop, // font.pointSize: 12 // font.family: "Helvetica" // } -// font is a nested property. size and family are not. +// font is a nested property. pointSize and family are not. bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &ctxt) @@ -1638,7 +1656,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, static_cast(QObjectPrivate::get(engine)); if (ep->valueTypes[prop->type]) { COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], - prop->value, ctxt.incr())); + prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { COMPILE_EXCEPTION(prop, "Invalid property access"); @@ -1662,6 +1680,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, bool QmlCompiler::buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt) { if (obj->defaultProperty) @@ -1683,13 +1702,16 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, if (value->object) { bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; - if (!isPropertyValue) { + bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; + if (!isPropertyValue && !isPropertyInterceptor) { COMPILE_EXCEPTION(prop, "Invalid property use"); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); - value->type = Value::ValueSource; - } + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(baseObj, ForceCreation); + value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; + } } else if (value->value.isScript()) { // ### Check for writability BindingReference reference; @@ -1854,8 +1876,12 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, // Will be true if the assigned type inherits QmlPropertyValueSource bool isPropertyValue = false; - if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) + // Will be true if the assigned type inherits QmlPropertyValueInterceptor + bool isPropertyInterceptor = false; + if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) { isPropertyValue = valueType->propertyValueSourceCast() != -1; + isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1; + } // We want to raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might @@ -1892,11 +1918,13 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, component->getDefaultProperty()->addValue(componentValue); v->object = component; COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); - } else if (isPropertyValue) { + } else if (isPropertyValue || isPropertyInterceptor) { // Assign as a property value source COMPILE_CHECK(buildObject(v->object, ctxt)); - v->type = Value::ValueSource; + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(prop->parent, ForceCreation); + v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { COMPILE_EXCEPTION(v->object, "Cannot assign object to property"); } @@ -2002,7 +2030,8 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(obj); Q_ASSERT(obj->metatype); - if (obj->dynamicProperties.isEmpty() && + if (mode != ForceCreation && + obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty() && obj->dynamicSlots.isEmpty()) return true; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1d27342..3a35d58 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -191,6 +191,7 @@ private: const BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt); bool buildListProperty(QmlParser::Property *prop, QmlParser::Object *obj, @@ -209,7 +210,7 @@ private: bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj); bool testLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *value); - enum DynamicMetaMode { IgnoreAliases, ResolveAliases }; + enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; bool mergeDynamicMetaProperties(QmlParser::Object *obj); bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode); bool checkDynamicMeta(QmlParser::Object *obj); diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 5b1cbeb..9a761b2 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -573,7 +573,7 @@ void QmlComponentPrivate::completeCreate() bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) - bv.at(jj)->setEnabled(true); + bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } QmlEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 18439f4..a465445 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -149,6 +149,9 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreValueSource: qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; break; + case QmlInstruction::StoreValueInterceptor: + qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue; + break; case QmlInstruction::BeginObject: qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue; break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 1dcdace..88dff2d 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -130,6 +130,7 @@ public: StoreIdOptBinding, /* assignIdOptBinding */ StoreObjPropBinding, /* assignObjPropBinding */ StoreValueSource, /* assignValueSource */ + StoreValueInterceptor, /* assignValueInterceptor */ BeginObject, /* begin */ @@ -190,6 +191,11 @@ public: } assignValueSource; struct { int property; + int owner; + int castValue; + } assignValueInterceptor; //### merge with above + struct { + int property; int value; short context; short owner; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 302ce8c..7a7e074 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -559,17 +559,17 @@ QmlAbstractBinding *QmlMetaProperty::binding() const is assumed by the caller. */ QmlAbstractBinding * -QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const +QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - return d->setBinding(d->object, d->core, newBinding); + return d->setBinding(d->object, d->core, newBinding, flags); } QmlAbstractBinding * QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core, - QmlAbstractBinding *newBinding) + QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) { QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding); @@ -581,7 +581,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data binding->setEnabled(false); if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return binding; // ### QmlAbstractBinding; } @@ -591,7 +591,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data } if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return 0; } @@ -752,11 +752,52 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() } } +//### +//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC! +//### +bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags) +{ + if (!object || !prop.isWritable()) + return false; + + QVariant v = value; + uint t = QVariant::Invalid; + if (prop.isEnumType()) { + QMetaEnum menum = prop.enumerator(); + if (v.type() == QVariant::String +#ifdef QT3_SUPPORT + || v.type() == QVariant::CString +#endif + ) { + if (prop.isFlagType()) + v = QVariant(menum.keysToValue(value.toByteArray())); + else + v = QVariant(menum.keyToValue(value.toByteArray())); + } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) { + int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name()); + if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData()) + return false; + v = QVariant(*reinterpret_cast(v.constData())); + } + v.convert(QVariant::Int); + } + + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value, return the value of status + int status = -1; + void *argv[] = { v.data(), &v, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv); + return status; +} + void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, - QmlMetaProperty::WriteSource source) + QmlMetaProperty::WriteFlags flags) { // Remove any existing bindings on this property - if (source != QmlMetaProperty::Binding) + if (!(flags & QmlMetaProperty::DontRemoveBinding)) delete q->setBinding(0); uint type = q->type(); @@ -776,22 +817,23 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlPropertyCache::Data data = core; data.coreIndex = valueTypeCoreIdx; data.propType = valueTypePropType; - write(writeBack, data, value, context); + write(writeBack, data, value, context, flags); - writeBack->write(object, core.coreIndex); + writeBack->write(object, core.coreIndex, flags); if (!ep) delete writeBack; } else { - write(object, core, value, context); + write(object, core, value, context, flags); } } void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property, - const QVariant &value, QmlContext *context) + const QVariant &value, QmlContext *context, QmlMetaProperty::WriteFlags flags) { int coreIdx = property.coreIndex; + int status = -1; //for dbus if (property.flags & QmlPropertyCache::Data::IsEnumType) { QMetaProperty prop = object->metaObject()->property(property.coreIndex); @@ -803,7 +845,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (qFuzzyCompare(fractional, (double)0.0)) v.convert(QVariant::Int); } - prop.write(object, v); + writeEnumProperty(prop, coreIdx, object, v, flags); return; } @@ -836,14 +878,12 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data } else if (vt == t) { - void *a[1]; - a[0] = (void *)value.constData(); + void *a[] = { (void *)value.constData(), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (qMetaTypeId() == t) { - void *a[1]; - a[0] = (void *)&value; + void *a[] = { (void *)&value, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) { @@ -867,7 +907,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (valMo || !o) { - void *args[] = { &o, 0 }; + void *args[] = { &o, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args); @@ -933,16 +973,14 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data QVariant v = value; if (v.convert((QVariant::Type)t)) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) { QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t); if (con) { QVariant v = con(value.toString()); if (v.userType() == t) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } } @@ -955,10 +993,10 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data */ void QmlMetaProperty::write(const QVariant &value) const { - write(value, Other); + write(value, 0); } -void QmlMetaProperty::write(const QVariant &value, WriteSource source) const +void QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const { if (!d->object) return; @@ -969,7 +1007,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const } else if (d->core.isValid()) { - d->writeValueProperty(value, source); + d->writeValueProperty(value, flags); } } diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 8c34ece..b0ae28c 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -88,8 +88,9 @@ public: QVariant read() const; void write(const QVariant &) const; - enum WriteSource { Animation, Binding, Other }; - void write(const QVariant &, WriteSource) const; + enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 }; + Q_DECLARE_FLAGS(WriteFlags, WriteFlag) + void write(const QVariant &, QmlMetaProperty::WriteFlags) const; bool hasChangedNotifier() const; bool needsChangedNotifier() const; @@ -126,7 +127,8 @@ public: QMetaProperty property() const; QmlAbstractBinding *binding() const; - QmlAbstractBinding *setBinding(QmlAbstractBinding *) const; + QmlAbstractBinding *setBinding(QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const; QmlExpression *signalExpression() const; QmlExpression *setSignalExpression(QmlExpression *) const; @@ -139,6 +141,7 @@ private: QmlMetaPropertyPrivate *d; }; typedef QList QmlMetaProperties; + Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags) QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 00b9c3a..a856b90 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -99,9 +99,12 @@ public: void writeSignalProperty(const QVariant &); QVariant readValueProperty(); - void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); - static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); - static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *); + void writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags); + static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags); + static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *, + QmlMetaProperty::WriteFlags flags = 0); + static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding); static quint32 saveValueType(int, int); static quint32 saveProperty(int); diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index c40232f..5198f9f 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -128,6 +128,7 @@ public: const QMetaObject *m_attachedPropertiesType; int m_parserStatusCast; int m_propertyValueSourceCast; + int m_propertyValueInterceptorCast; QmlPrivate::CreateFunc m_extFunc; const QMetaObject *m_extMetaObject; int m_index; @@ -140,8 +141,8 @@ public: QmlTypePrivate::QmlTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0), m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), - m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_extFunc(0), m_extMetaObject(0), - m_index(-1), m_customParser(0), m_isSetup(false) + m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), + m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { } @@ -169,7 +170,8 @@ QmlType::QmlType(int type, int listType, int qmlListType, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, const QMetaObject *attachedType, - int parserStatusCast, int propertyValueSourceCast, QmlPrivate::CreateFunc extFunc, + int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast, + QmlPrivate::CreateFunc extFunc, const QMetaObject *extMetaObject, int index, QmlCustomParser *customParser) : d(new QmlTypePrivate) @@ -187,6 +189,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_attachedPropertiesType = attachedType; d->m_parserStatusCast = parserStatusCast; d->m_propertyValueSourceCast = propertyValueSourceCast; + d->m_propertyValueInterceptorCast = propertyValueInterceptorCast; d->m_extFunc = extFunc; d->m_index = index; d->m_customParser = customParser; @@ -412,6 +415,11 @@ int QmlType::propertyValueSourceCast() const return d->m_propertyValueSourceCast; } +int QmlType::propertyValueInterceptorCast() const +{ + return d->m_propertyValueInterceptorCast; +} + QVariant QmlType::fromObject(QObject *obj) const { QVariant rv; @@ -467,7 +475,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *uri, int version_maj, int version_min_from, int version_min_to, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, - int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) + int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) { Q_UNUSED(object); @@ -492,7 +500,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus, - valueSource, extFunc, extmo, index, parser); + valueSource, valueInterceptor, extFunc, extmo, index, parser); data->types.append(type); data->idToType.insert(type->typeId(), type); @@ -539,6 +547,17 @@ int QmlMetaType::qmlPropertyValueSourceCast(int userType) return -1; } +int QmlMetaType::qmlPropertyValueInterceptorCast(int userType) +{ + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + QmlType *type = data->idToType.value(userType); + if (type && type->typeId() == userType) + return type->propertyValueInterceptorCast(); + else + return -1; +} + QObject *QmlMetaType::toQObject(const QVariant &v) { if (!isObject(v.userType())) diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 02c817d..42c278c 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -48,6 +48,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -60,7 +61,7 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); + static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); static bool copy(int type, void *data, const void *copy = 0); @@ -80,6 +81,7 @@ public: static QObject *toQObject(const QVariant &); static int qmlParserStatusCast(int); static int qmlPropertyValueSourceCast(int); + static int qmlPropertyValueInterceptorCast(int); static int listType(int); static bool clear(const QVariant &); static bool append(const QVariant &, const QVariant &); @@ -146,6 +148,7 @@ public: QVariant fromObject(QObject *) const; const char *interfaceIId() const; int propertyValueSourceCast() const; + int propertyValueInterceptorCast() const; int index() const; private: @@ -153,7 +156,7 @@ private: friend class QmlTypePrivate; friend class QmlMetaTypeData; QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -176,6 +179,7 @@ int qmlRegisterType(const char *typeName) QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), 0, 0, 0); } @@ -196,7 +200,8 @@ int qmlRegisterType(const char *uri, int version_maj, int version_min_from, int QmlPrivate::attachedPropertiesMetaObject(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), - QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), 0, 0, 0); } @@ -224,6 +229,7 @@ int qmlRegisterExtendedType(const char *typeName) QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), &QmlPrivate::CreateParent::create, &E::staticMetaObject, 0); } @@ -253,6 +259,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min_fr QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), &QmlPrivate::CreateParent::create, &E::staticMetaObject, 0); } @@ -290,6 +297,7 @@ int qmlRegisterCustomType(const char *uri, int version_maj, int version_min_from QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), + QmlPrivate::StaticCastSelector::cast(), 0, 0, parser); } diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8c46939..bae263a 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -282,6 +282,9 @@ void QmlParser::Value::dump(int indent) const case Value::ValueSource: type = "ValueSource"; break; + case Value::ValueInterceptor: + type = "ValueInterceptor"; + break; case Value::CreatedObject: type = "CreatedObject"; break; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 16862eb..e11e164 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -273,6 +273,8 @@ namespace QmlParser PropertyBinding, // This is used as a QmlPropertyValueSource assignment ValueSource, + // This is used as a QmlPropertyValueInterceptor assignment + ValueInterceptor, // This is used as a property QObject assignment CreatedObject, // This is used as a signal object assignment diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp index 4ae2070..84c9ecb 100644 --- a/src/declarative/qml/qmlvaluetype.cpp +++ b/src/declarative/qml/qmlvaluetype.cpp @@ -97,9 +97,10 @@ void QmlPointFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointFValueType::write(QObject *obj, int idx) +void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -144,9 +145,10 @@ void QmlPointValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointValueType::write(QObject *obj, int idx) +void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -191,9 +193,10 @@ void QmlSizeFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeFValueType::write(QObject *obj, int idx) +void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -238,9 +241,10 @@ void QmlSizeValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeValueType::write(QObject *obj, int idx) +void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -285,9 +289,10 @@ void QmlRectFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectFValueType::write(QObject *obj, int idx) +void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -352,9 +357,10 @@ void QmlRectValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectValueType::write(QObject *obj, int idx) +void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -419,9 +425,10 @@ void QmlVector3DValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlVector3DValueType::write(QObject *obj, int idx) +void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &vector, 0 }; + int status = -1; + void *a[] = { &vector, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -476,9 +483,10 @@ void QmlFontValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlFontValueType::write(QObject *obj, int idx) +void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &font, 0 }; + int status = -1; + void *a[] = { &font, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h index da5e972..d3adf1e 100644 --- a/src/declarative/qml/qmlvaluetype_p.h +++ b/src/declarative/qml/qmlvaluetype_p.h @@ -58,6 +58,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -67,7 +68,7 @@ class QmlValueType : public QObject public: QmlValueType(QObject *parent = 0); virtual void read(QObject *, int) = 0; - virtual void write(QObject *, int) = 0; + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0; virtual QVariant value() = 0; virtual void setValue(QVariant) = 0; }; @@ -92,7 +93,7 @@ public: QmlPointFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -114,7 +115,7 @@ public: QmlPointValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -136,7 +137,7 @@ public: QmlSizeFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -158,7 +159,7 @@ public: QmlSizeValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -182,7 +183,7 @@ public: QmlRectFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -211,7 +212,7 @@ public: QmlRectValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -239,7 +240,7 @@ public: QmlVector3DValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -267,7 +268,7 @@ public: QmlFontValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 6fd674a..6a7bdeb 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -132,7 +132,7 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object, ref.type->read(ref.object, ref.property); QMetaProperty p = ref.type->metaObject()->property(id); p.write(ref.type, v); - ref.type->write(ref.object, ref.property); + ref.type->write(ref.object, ref.property, 0); } QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index e4eef64..93c02b3 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -155,6 +155,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine()); QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt); + int status = -1; //for dbus + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor; + for (int ii = start; !isError() && ii < (start + count); ++ii) { QmlInstruction &instr = comp->bytecode[ii]; @@ -275,10 +278,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreVariant: { QObject *target = stack.top(); - void *a[1]; // XXX - can be more efficient QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value)); - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -287,8 +289,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreString: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&primitives.at(instr.storeString.value); + void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -297,9 +298,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreUrl: { QObject *target = stack.top(); - void *a[1]; QUrl u(primitives.at(instr.storeUrl.value)); - a[0] = (void *)&u; + void *a[] = { &u, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeUrl.propertyIndex, a); } @@ -309,8 +309,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, { QObject *target = stack.top(); float f = instr.storeFloat.value; - void *a[1]; - a[0] = &f; + void *a[] = { &f, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeFloat.propertyIndex, a); } @@ -320,8 +319,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, { QObject *target = stack.top(); double d = instr.storeDouble.value; - void *a[1]; - a[0] = &d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDouble.propertyIndex, a); } @@ -330,8 +328,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreBool: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeBool.value; + void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeBool.propertyIndex, a); } @@ -340,8 +337,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreInteger: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeInteger.value; + void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeInteger.propertyIndex, a); } @@ -350,9 +346,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreColor: { QObject *target = stack.top(); - void *a[1]; QColor c = QColor::fromRgba(instr.storeColor.value); - a[0] = (void *)&c; + void *a[] = { &c, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeColor.propertyIndex, a); } @@ -361,9 +356,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreDate: { QObject *target = stack.top(); - void *a[1]; QDate d = QDate::fromJulianDay(instr.storeDate.value); - a[0] = (void *)&d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDate.propertyIndex, a); } @@ -372,13 +366,12 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeTime.valueIndex), intData.at(instr.storeTime.valueIndex+1), intData.at(instr.storeTime.valueIndex+2), intData.at(instr.storeTime.valueIndex+3)); - a[0] = (void *)&t; + void *a[] = { &t, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeTime.propertyIndex, a); } @@ -387,14 +380,13 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreDateTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), intData.at(instr.storeDateTime.valueIndex+2), intData.at(instr.storeDateTime.valueIndex+3), intData.at(instr.storeDateTime.valueIndex+4)); QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); - a[0] = (void *)&dt; + void *a[] = { &dt, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDateTime.propertyIndex, a); } @@ -403,10 +395,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StorePoint: { QObject *target = stack.top(); - void *a[1]; QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -415,10 +406,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StorePointF: { QObject *target = stack.top(); - void *a[1]; QPointF p(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -427,10 +417,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreSize: { QObject *target = stack.top(); - void *a[1]; QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -439,10 +428,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreSizeF: { QObject *target = stack.top(); - void *a[1]; QSizeF s(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&s; + void *a[] = { &s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -451,12 +439,11 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreRect: { QObject *target = stack.top(); - void *a[1]; QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)).toRect(); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -465,12 +452,11 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreRectF: { QObject *target = stack.top(); - void *a[1]; QRectF r(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -479,11 +465,10 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreVector3D: { QObject *target = stack.top(); - void *a[1]; QVector3D p(floatData.at(instr.storeVector3D.valueIndex), floatData.at(instr.storeVector3D.valueIndex+1), floatData.at(instr.storeVector3D.valueIndex+2)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeVector3D.propertyIndex, a); } @@ -494,9 +479,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QObject *assignObj = stack.pop(); QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&assignObj; - + void *a[] = { (void *)&assignObj, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -506,7 +489,6 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::AssignCustomType: { QObject *target = stack.top(); - void *a[1]; QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); const QString &primitive = primitives.at(data.index); QmlMetaType::StringConverter converter = @@ -518,7 +500,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name()); - a[0] = (void *)v.data(); + void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.assignCustomType.propertyIndex, a); } @@ -654,6 +636,20 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, } break; + case QmlInstruction::StoreValueInterceptor: + { + QObject *obj = stack.pop(); + QmlPropertyValueInterceptor *vi = reinterpret_cast(reinterpret_cast(obj) + instr.assignValueInterceptor.castValue); + QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); + QmlMetaProperty prop; + prop.restore(instr.assignValueInterceptor.property, target, ctxt); + obj->setParent(target); + vi->setTarget(prop); + QmlVMEMetaObject *mo = static_cast((QMetaObject*)target->metaObject()); + mo->registerInterceptor(prop.coreIndex(), vi); + } + break; + case QmlInstruction::StoreObjectQmlList: { QObject *assign = stack.pop(); @@ -705,8 +701,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QObject *target = stack.top(); QVariant v = QVariant::fromValue(assign); - void *a[1]; - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -725,8 +720,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (iid) { void *ptr = assign->qt_metacast(iid); if (ptr) { - void *a[1]; - a[0] = &ptr; + void *a[] = { &ptr, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIdx, a); @@ -848,7 +842,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QmlValueType *valueHandler = static_cast(stack.pop()); QObject *target = stack.top(); - valueHandler->write(target, instr.fetchValue.property); + valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index f473743..5ef1158 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -100,6 +100,24 @@ QmlVMEMetaObject::~QmlVMEMetaObject() int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) { int id = _id; + if(c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast(a[3]); + if (!(flags & QmlMetaProperty::BypassInterceptor) + && !aInterceptors.isEmpty() + && aInterceptors.testBit(id)) { + QmlPropertyValueInterceptor *vi = interceptors.value(id); + if (id >= propOffset) { + id -= propOffset; + if (id < metaData->propertyCount) { + vi->write(QVariant(data[id].type(), a[0])); + return -1; + } + } else { + vi->write(QVariant(property(id).type(), a[0])); + return -1; + } + } + } if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) { if (id >= propOffset) { id -= propOffset; @@ -253,4 +271,13 @@ void QmlVMEMetaObject::listChanged(int id) activate(object, methodOffset + id, 0); } +void QmlVMEMetaObject::registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor) +{ + if (aInterceptors.isEmpty()) + aInterceptors.resize(propertyCount() + metaData->propertyCount); + aInterceptors.setBit(index); + interceptors.insert(index, interceptor); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 1c26241..d376f4c 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -104,6 +104,8 @@ public: QmlRefCount * = 0); ~QmlVMEMetaObject(); + void registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor); + protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); @@ -117,6 +119,8 @@ private: QVariant *data; QBitArray aConnected; + QBitArray aInterceptors; + QHash interceptors; QAbstractDynamicMetaObject *parent; diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 3edbc5f..247e64c 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -972,7 +972,7 @@ void QmlPropertyAction::setValue(const QVariant &v) void QmlPropertyActionPrivate::doAction() { - property.write(value); + property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } QAbstractAnimation *QmlPropertyAction::qtAnimation() @@ -1007,9 +1007,7 @@ void QmlPropertyAction::transition(QmlStateActions &actions, { for (int ii = 0; ii < actions.count(); ++ii) { const Action &action = actions.at(ii); - QmlBehavior::_ignore = true; - action.property.write(action.toValue); - QmlBehavior::_ignore = false; + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } }; @@ -1020,9 +1018,11 @@ void QmlPropertyAction::transition(QmlStateActions &actions, if (!d->propertyName.isEmpty() && !props.contains(d->propertyName)) props.append(d->propertyName); + bool targetNeedsReset = false; if (d->userProperty.isValid() && props.isEmpty() && !target()) { props.append(d->userProperty.value.name()); d->target = d->userProperty.value.object(); + targetNeedsReset = true; } QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; @@ -1070,6 +1070,8 @@ void QmlPropertyAction::transition(QmlStateActions &actions, } else { delete data; } + if (targetNeedsReset) + d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAction,QmlPropertyAction) @@ -1714,10 +1716,10 @@ void QmlPropertyAnimationPrivate::valueChanged(qreal r) } if (r == 1.) { - property.write(to); + property.write(to, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else { if (interpolator) - property.write(interpolator(from.constData(), to.constData(), r)); + property.write(interpolator(from.constData(), to.constData(), r), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } @@ -1773,9 +1775,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; - QmlBehavior::_ignore = true; if (v == 1.) - action.property.write(action.toValue); + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); else { if (action.fromValue.isNull()) { action.fromValue = action.property.read(); @@ -1790,9 +1791,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, } } if (interpolator) - action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v)); + action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } - QmlBehavior::_ignore = false; } } }; @@ -1805,9 +1805,11 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false; + bool targetNeedsReset = false; if (d->userProperty.isValid() && props.isEmpty() && !target()) { props.append(d->userProperty.value.name()); d->target = d->userProperty.value.object(); + targetNeedsReset = true; } PropertyUpdater *data = new PropertyUpdater; @@ -1874,6 +1876,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, } else { delete data; } + if (targetNeedsReset) + d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAnimation,QmlPropertyAnimation) diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index 3e2e05f..7eaccac 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -144,9 +144,9 @@ void QmlTransitionManager::transition(const QList &list, for (int ii = 0; ii < applyList.size(); ++ii) { const Action &action = applyList.at(ii); if (action.toBinding) { - action.property.setBinding(action.toBinding); + action.property.setBinding(action.toBinding, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else if (!action.event) { - action.property.write(action.toValue); + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else if (action.event->isReversable()) { if (action.reverseEvent) action.event->reverse(); @@ -187,7 +187,7 @@ void QmlTransitionManager::transition(const QList &list, if (action.toBinding) action.property.setBinding(0); // Make sure this is disabled during the transition - action.property.write(action.fromValue); + action.property.write(action.fromValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } @@ -223,7 +223,7 @@ void QmlTransitionManager::transition(const QList &list, } // Any actions remaining have not been handled by the transition and should - // be applied immediately. We skip applying transitions, as they are all + // be applied immediately. We skip applying bindings, as they are all // applied at the end in applyBindings() to avoid any nastiness mid // transition foreach(const Action &action, applyList) { @@ -232,13 +232,12 @@ void QmlTransitionManager::transition(const QList &list, action.event->reverse(); else action.event->execute(); - } else if (!action.event) { + } else if (!action.event && !action.toBinding) { action.property.write(action.toValue); } } if (!transition) d->applyBindings(); - } void QmlTransitionManager::cancel() -- cgit v0.12 From da0e40dfefb7fc487a9a775363321e178e529d16 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 12 Oct 2009 09:33:32 +1000 Subject: Make sure ParentChange always saves original parent. --- src/declarative/util/qmlstate.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index 3c85db7..98facd9 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -350,6 +350,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever if (action.event) { if (!action.event->isReversable()) continue; + action.event->saveOriginals(); for (jj = 0; jj < d->revertList.count(); ++jj) { ActionEvent *event = d->revertList.at(jj).event; if (event && event->typeName() == action.event->typeName()) { @@ -359,9 +360,6 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever } } } - if (!found) - action.event->saveOriginals(); - //### do we ever need to do saveOriginals when found == true? } else { action.fromBinding = action.property.binding(); -- cgit v0.12 From ba1191f30ff2886b477041092eb40d7d9781b63f Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 12 Oct 2009 09:34:46 +1000 Subject: Correctly identify signal handlers in PropertyChanges when !isScript. --- src/declarative/util/qmlpropertychanges.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp index a5a08bc..b07a79f 100644 --- a/src/declarative/util/qmlpropertychanges.cpp +++ b/src/declarative/util/qmlpropertychanges.cpp @@ -230,17 +230,18 @@ void QmlPropertyChangesPrivate::decode() ds >> isScript; ds >> data; - if (isScript) { - QmlMetaProperty prop = property(name); //### can we avoid or reuse? + QmlMetaProperty prop = property(name); //### better way to check for signal property? + if (prop.type() == QmlMetaProperty::SignalProperty) { QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object); expression->setTrackChange(false); - if (prop.type() == QmlMetaProperty::SignalProperty) { - QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler; - handler->property = prop; - handler->expression = expression; - signalReplacements << handler; - } else - expressions << qMakePair(name, expression); + QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler; + handler->property = prop; + handler->expression = expression; + signalReplacements << handler; + } else if (isScript) { + QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object); + expression->setTrackChange(false); + expressions << qMakePair(name, expression); } else { properties << qMakePair(name, data); } -- cgit v0.12 From eca4d3662d61aea60478772d8cfa477642d284df Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 12 Oct 2009 10:26:55 +1000 Subject: Add missing files. --- .../qml/qmlpropertyvalueinterceptor.cpp | 77 ++++++++++++++++++++++ src/declarative/qml/qmlpropertyvalueinterceptor.h | 68 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/declarative/qml/qmlpropertyvalueinterceptor.cpp create mode 100644 src/declarative/qml/qmlpropertyvalueinterceptor.h diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp new file mode 100644 index 0000000..86905e6 --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 "qmlpropertyvalueinterceptor.h" +#include "qml.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QmlPropertyValueInterceptor + \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior. + + This class intercepts property writes, allowing for custom handling. For example, Behavior uses this + interception to provide a default animation for all changes to a property's value. + */ + +/*! + Constructs a QmlPropertyValueInterceptor. +*/ +QmlPropertyValueInterceptor::QmlPropertyValueInterceptor() +{ +} + +QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor() +{ +} + +/*! + \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property) + Set the target \a property for the value interceptor. This method will + be called by the QML engine when assigning a value interceptor. +*/ + +/*! + \fn void QmlPropertyValueInterceptor::write(const QVariant &value) + This method will be called when a new \a value is assigned to the property being intercepted. +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h new file mode 100644 index 0000000..678c12c --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 QMLPROPERTYVALUEINTERCEPTOR_H +#define QMLPROPERTYVALUEINTERCEPTOR_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlMetaProperty; +class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor +{ +public: + QmlPropertyValueInterceptor(); + virtual ~QmlPropertyValueInterceptor(); + virtual void setTarget(const QmlMetaProperty &property) = 0; + virtual void write(const QVariant &value) = 0; +}; +Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLPROPERTYVALUEINTERCEPTOR_H -- cgit v0.12 From 86cd2fa6836c90ed329eb1f0507eeb311810c194 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 12 Oct 2009 10:31:59 +1000 Subject: unwarn --- src/declarative/util/qmltimer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/declarative/util/qmltimer.cpp b/src/declarative/util/qmltimer.cpp index fdc57ff..3fbe15c 100644 --- a/src/declarative/util/qmltimer.cpp +++ b/src/declarative/util/qmltimer.cpp @@ -207,7 +207,6 @@ void QmlTimer::setTriggeredOnStart(bool triggeredOnStart) */ void QmlTimer::start() { - Q_D(QmlTimer); setRunning(true); } @@ -220,7 +219,6 @@ void QmlTimer::start() */ void QmlTimer::stop() { - Q_D(QmlTimer); setRunning(false); } -- cgit v0.12 From 4d6958dd6d62441d98826ce141b5824d7eb0dfb0 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 11:14:04 +1000 Subject: The root object is always last default object Fix for QT-2301 --- src/declarative/qml/qmlbasicscript.cpp | 6 ++++- .../qmlecmascript/data/signalTriggeredBindings.qml | 20 ++++++++++++++++ .../qmlecmascript/tst_qmlecmascript.cpp | 28 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index f3f9289..f8ef2e7 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP); + using namespace QmlJS; struct ScriptInstruction { @@ -400,6 +402,8 @@ bool QmlBasicScript::compile(const Expression &expression) ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count()); } + if (d && qmlBasicScriptDump()) + dump(); return d != 0; } @@ -649,7 +653,7 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) case ScriptInstruction::FetchRootConstant: { - QObject *obj = contextPrivate->defaultObjects.at(0); + QObject *obj = contextPrivate->defaultObjects.last(); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); if (obj && instr.constant.notify != 0) diff --git a/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml b/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml new file mode 100644 index 0000000..f65e253 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/signalTriggeredBindings.qml @@ -0,0 +1,20 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + property real base: 50 + property alias test1: myObject.test1 + property alias test2: myObject.test2 + + objectProperty: Object { + id: myObject + property real test1: base + property real test2: Math.max(0, base) + } + + // Signal with no args + onBasicSignal: base = 200 + // Signal with args + onArgumentSignal: base = 400 +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 5e04f7c..f976e41 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -62,6 +62,7 @@ private slots: void selfDeletingBinding(); void extendedObjectPropertyLookup(); void scriptErrors(); + void signalTriggeredBindings(); private: QmlEngine engine; @@ -759,6 +760,33 @@ void tst_qmlecmascript::scriptErrors() QVERIFY(object != 0); } +/* +Test bindings still work when the reeval is triggered from within +a signal script. +*/ +void tst_qmlecmascript::signalTriggeredBindings() +{ + QmlComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml")); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("base").toReal(), 50.); + QCOMPARE(object->property("test1").toReal(), 50.); + QCOMPARE(object->property("test2").toReal(), 50.); + + object->basicSignal(); + + QCOMPARE(object->property("base").toReal(), 200.); + QCOMPARE(object->property("test1").toReal(), 200.); + QCOMPARE(object->property("test2").toReal(), 200.); + + object->argumentSignal(10, QString(), 10); + + QCOMPARE(object->property("base").toReal(), 400.); + QCOMPARE(object->property("test1").toReal(), 400.); + QCOMPARE(object->property("test2").toReal(), 400.); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From 68c69f88d4c3a7b9f24162a4c7708ded7caba90e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 11:23:22 +1000 Subject: Reenable behaviors (now that they work again!) --- examples/declarative/snow/ImageBatch.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/declarative/snow/ImageBatch.qml b/examples/declarative/snow/ImageBatch.qml index 86e11f7..3945087 100644 --- a/examples/declarative/snow/ImageBatch.qml +++ b/examples/declarative/snow/ImageBatch.qml @@ -42,7 +42,7 @@ GridView { width: grid.imageWidth; height: grid.imageHeight; Image { id: flickrImage; source: url; fillMode: "PreserveAspectFit"; smooth: true; anchors.fill: parent; - opacity: (status == Image.Ready)?1:0; /*opacity: Behavior { NumberAnimation { properties: "opacity" } }*/ } + opacity: (status == Image.Ready)?1:0; opacity: Behavior { NumberAnimation { properties: "opacity" } } } Loading { anchors.centerIn: parent; visible: flickrImage.status!=1 } states: State { -- cgit v0.12 From 4a49c007c8344c8baa62b66afd3c9c672cb2611f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 12 Oct 2009 11:23:48 +1000 Subject: update --- src/declarative/QmlChanges.txt | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index ee5acd4..0df0613 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -1,10 +1,9 @@ QML API Review ============== -The QML API is being reviewed from 17 to 4 September 2009. This -file documents the changes. Note that the changes are incremental, -so a rename A->B for example may be follow by another subseqent -rename B->C, if later reviews override earlier reviews. +The QML API is being reviewed. This file documents the changes. +Note that the changes are incremental, so a rename A->B for example may be followed +by another subsequent rename B->C, if later reviews override earlier reviews. API Changes =========== @@ -95,21 +94,13 @@ ListView: removed currentItemMode. Replaced by highligh range. ListView: removed snapPos. Other Changes: +ids must be lowercase: Text { id: foo }, not Text { id: Foo } Drag: axis becomes an enum with values "XAxis", "YAxis", "XandYAxis" Image: scaleGrid property removed. New item called BorderImage instead. KeyActions: changed to a Keys attached property on any item. KeyProxy: changed to a Keys.forwardTo property on any item. - -Pending Changes -=============== - -Renamed elements: - -Renamed properties: - -Removed Properties: -PropertyAction::property -PropertyAction::target (if possible) - -Additions: -Connection: add "slot" property +Script: now an intrinsic type in the language + - cannot be assigned to properties + - good: Item { Script { ... } } + - bad: Item { resources: Script { ... } } +Script: delay-loaded of the QML file until their source has been loaded (this only effects QML files loaded across the network.) -- cgit v0.12 From 6a4f57c100e8c27bbe8ad3975bd99383063dafa1 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 12 Oct 2009 11:27:26 +1000 Subject: update --- src/declarative/QmlChanges.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index 0df0613..6a6c394 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -104,3 +104,4 @@ Script: now an intrinsic type in the language - good: Item { Script { ... } } - bad: Item { resources: Script { ... } } Script: delay-loaded of the QML file until their source has been loaded (this only effects QML files loaded across the network.) +Scope: declared properties shadow a property of the same name (was previously the reverse) -- cgit v0.12 From 6be94173f3f209d785e5787df8440d20ff0f2709 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 13:00:08 +1000 Subject: Use utf8 instead of latin1 where appropriate --- src/declarative/debugger/qmldebug.cpp | 2 +- src/declarative/debugger/qmldebugservice.cpp | 2 +- src/declarative/extra/qbindablemap.cpp | 8 ++++---- src/declarative/fx/qfxpathview.cpp | 2 +- src/declarative/fx/qfxvisualitemmodel.cpp | 14 +++++++------- src/declarative/fx/qfxwebview.cpp | 7 +++---- src/declarative/qml/qmlbasicscript.cpp | 2 +- src/declarative/qml/qmlcompiler.cpp | 14 +++++++------- src/declarative/qml/qmlcompositetypemanager.cpp | 8 ++++---- src/declarative/qml/qmlengine.cpp | 8 ++++---- src/declarative/qml/qmlenginedebug.cpp | 4 ++-- src/declarative/qml/qmlexpression.cpp | 2 +- src/declarative/qml/qmlinfo.cpp | 2 +- src/declarative/qml/qmlintegercache.cpp | 2 +- src/declarative/qml/qmlmetaproperty.cpp | 10 +++++----- src/declarative/qml/qmlobjectscriptclass.cpp | 2 +- src/declarative/qml/qmlpropertycache.cpp | 10 +++++----- src/declarative/qml/qmlscriptparser.cpp | 6 +++--- src/declarative/qml/qmlvme.cpp | 2 +- src/declarative/util/qmlanimation.cpp | 12 ++++++------ src/declarative/util/qmlconnection.cpp | 4 ++-- src/declarative/util/qmllistmodel.cpp | 8 ++++---- 22 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp index a515c1d..1ef7503 100644 --- a/src/declarative/debugger/qmldebug.cpp +++ b/src/declarative/debugger/qmldebug.cpp @@ -276,7 +276,7 @@ QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toLatin1(); + ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8(); d->client->sendMessage(message); } else { watch->m_state = QmlDebugWatch::Dead; diff --git a/src/declarative/debugger/qmldebugservice.cpp b/src/declarative/debugger/qmldebugservice.cpp index b83a4b1..6913def 100644 --- a/src/declarative/debugger/qmldebugservice.cpp +++ b/src/declarative/debugger/qmldebugservice.cpp @@ -353,7 +353,7 @@ QString QmlDebugService::objectToString(QObject *obj) if(objectName.isEmpty()) objectName = QLatin1String(""); - QString rv = QLatin1String(obj->metaObject()->className()) + + QString rv = QString::fromUtf8(obj->metaObject()->className()) + QLatin1String(": ") + objectName; return rv; diff --git a/src/declarative/extra/qbindablemap.cpp b/src/declarative/extra/qbindablemap.cpp index c8c8ced..5254e2a 100644 --- a/src/declarative/extra/qbindablemap.cpp +++ b/src/declarative/extra/qbindablemap.cpp @@ -58,7 +58,7 @@ public: protected: virtual void propertyWrite(int index) { - map->emitChanged(QLatin1String(name(index))); + map->emitChanged(QString::fromUtf8(name(index))); } private: @@ -130,7 +130,7 @@ QBindableMap::~QBindableMap() void QBindableMap::clearValue(const QString &key) { //m_keys.remove(); //### - m_mo->setValue(key.toLatin1(), QVariant()); + m_mo->setValue(key.toUtf8(), QVariant()); //emit changed(key); } @@ -142,7 +142,7 @@ void QBindableMap::clearValue(const QString &key) */ QVariant QBindableMap::value(const QString &key) const { - return m_mo->value(key.toLatin1()); + return m_mo->value(key.toUtf8()); } /*! @@ -154,7 +154,7 @@ void QBindableMap::setValue(const QString &key, QVariant value) { if (!m_keys.contains(key)) m_keys.append(key); - m_mo->setValue(key.toLatin1(), value); + m_mo->setValue(key.toUtf8(), value); //emit changed(key); } diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp index b127f39..c580e98 100644 --- a/src/declarative/fx/qfxpathview.cpp +++ b/src/declarative/fx/qfxpathview.cpp @@ -607,7 +607,7 @@ void QFxPathViewPrivate::updateItem(QFxItem *item, qreal percent) { if (QObject *obj = QFxPathView::qmlAttachedProperties(item)) { foreach(const QString &attr, path->attributes()) - static_cast(obj)->setValue(attr.toLatin1(), path->attributeAt(attr, percent)); + static_cast(obj)->setValue(attr.toUtf8(), path->attributeAt(attr, percent)); } QPointF pf = path->pointAt(percent); item->setX(pf.x() - item->width()*item->scale()/2); diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index 943f909..3a9e5d4 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -264,7 +264,7 @@ public: for (QHash::const_iterator it = m_abstractItemModel->roleNames().begin(); it != m_abstractItemModel->roleNames().end(); ++it) { m_roles.append(it.key()); - m_roleNames.insert(QLatin1String(*it), it.key()); + m_roleNames.insert(QString::fromUtf8(*it), it.key()); } if (m_roles.count() == 1) m_roleNames.insert(QLatin1String("modelData"), m_roles.at(0)); @@ -416,11 +416,11 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { model->ensureRoles(); - if (model->m_roleNames.contains(QLatin1String(name))) + if (model->m_roleNames.contains(QString::fromUtf8(name))) return QmlOpenMetaObject::createProperty(name, type); } else { model->ensureRoles(); - const QLatin1String sname(name); + QString sname = QString::fromUtf8(name); if (model->m_roleNames.contains(sname)) return QmlOpenMetaObject::createProperty(name, type); } @@ -438,7 +438,7 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro Q_ASSERT(data->m_model); QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model); - QString name = QLatin1String(prop.name()); + QString name = QString::fromUtf8(prop.name()); if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { if (name == QLatin1String("modelData")) { if (model->m_listAccessor->type() == QmlListAccessor::Instance) { @@ -532,7 +532,7 @@ QFxVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &pr QFxVisualDataModel *m = new QFxVisualDataModel; m->setParent(object()); - m->setPart(QLatin1String(prop.name())); + m->setPart(QString::fromUtf8(prop.name())); m->setModel(QVariant::fromValue(static_cast(object())->model)); QVariant var = QVariant::fromValue((QObject *)m); @@ -706,7 +706,7 @@ QFxItem *QFxVisualDataModel::item(int index, bool complete) { Q_D(QFxVisualDataModel); if (d->m_visualItemModel) - return d->m_visualItemModel->item(index, d->m_part.toLatin1(), complete); + return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete); return item(index, QByteArray(), complete); } @@ -790,7 +790,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp if (!item) { QmlPackage *package = qobject_cast(nobj); if (package) { - QObject *o = package->part(QLatin1String(viewId)); + QObject *o = package->part(QString::fromUtf8(viewId)); item = qobject_cast(o); if (item) d->m_packaged.insertMulti(item, package); diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index a06e294..f7030ca 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -1325,9 +1325,8 @@ public Q_SLOTS: void qmlLoaded() { if (component->isError()) { - // XXX Could instead give these errors to the WebView to handle. - foreach (QmlError err, component->errors()) - qWarning(err.toString().toLatin1()); + // ### Could instead give these errors to the WebView to handle. + qWarning() << component->errors(); return; } item = qobject_cast(component->create(qmlContext(webview))); @@ -1335,7 +1334,7 @@ public Q_SLOTS: QString jsObjName; for (int i=0; isetProperty(propertyNames[i].toLatin1(),propertyValues[i]); + item->setProperty(propertyNames[i].toUtf8(),propertyValues[i]); if (propertyNames[i] == QLatin1String("objectname")) jsObjName = propertyValues[i]; } diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index f8ef2e7..a0d749f 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -369,7 +369,7 @@ bool QmlBasicScript::compile(const Expression &expression) { if (!expression.expression.asAST()) return false; - QByteArray expr = expression.expression.asScript().toLatin1(); + QByteArray expr = expression.expression.asScript().toUtf8(); const char *src = expr.constData(); QmlBasicScriptCompiler bsc; diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index f33731c..48d3360 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -195,14 +195,14 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, "Invalid property assignment:" << QLatin1String(prop.name()) << "is a read-only property"); + COMPILE_EXCEPTION(v, "Invalid property assignment:" << QString::fromUtf8(prop.name()) << "is a read-only property"); if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) COMPILE_EXCEPTION(v, "Invalid property assignment: unknown enumeration"); return true; @@ -336,9 +336,9 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = prop.propertyIndex(); @@ -595,7 +595,7 @@ bool QmlCompiler::compile(QmlEngine *engine, ref.ref = tref.unit; ref.ref->addref(); } - ref.className = parserRef->name.toLatin1(); + ref.className = parserRef->name.toUtf8(); out->types << ref; } @@ -2520,7 +2520,7 @@ QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj) return QStringList(); QMetaClassInfo classInfo = mo->classInfo(idx); - QStringList rv = QString(QLatin1String(classInfo.value())).split(QLatin1Char(',')); + QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); return rv; } diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index 71b4ef0..13bd02c 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -119,7 +119,7 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine) compiledComponent = new QmlCompiledData; compiledComponent->url = imports.baseUrl(); - compiledComponent->name = compiledComponent->url.toString().toLatin1(); // ### + compiledComponent->name = compiledComponent->url.toString().toUtf8(); QmlCompiler compiler; if (!compiler.compile(engine, this, compiledComponent)) { @@ -443,7 +443,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) int waiting = 0; for (int ii = 0; ii < types.count(); ++ii) { QmlScriptParser::TypeReference *parserRef = types.at(ii); - QByteArray typeName = parserRef->name.toLatin1(); + QByteArray typeName = parserRef->name.toUtf8(); QmlCompositeTypeData::TypeReference ref; @@ -458,7 +458,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) if (typeNamespace) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QLatin1String(typeName))); + error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); @@ -500,7 +500,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Type %1 unavailable").arg(QLatin1String(typeName))); + error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ccdf6cf..c644ccc 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -970,7 +970,7 @@ struct QmlEnginePrivate::ImportedNamespace { int vmin = minversions.at(i); if (isBuiltin.at(i)) { - QByteArray qt = urls.at(i).toLatin1(); + QByteArray qt = urls.at(i).toUtf8(); qt += "/"; qt += type; QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin); @@ -982,7 +982,7 @@ struct QmlEnginePrivate::ImportedNamespace { return true; } } else { - QUrl url = QUrl(urls.at(i) + QLatin1String("/" + type + ".qml")); + QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml")); if (vmaj || vmin) { // Check version file - XXX cache these in QmlEngine! QFile qmldir(QUrl(urls.at(i)+QLatin1String("/qmldir")).toLocalFile()); @@ -1101,7 +1101,7 @@ public: if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return)) return true; if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) { - *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QLatin1String(unqualifiedtype + ".qml"))); + *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml"))); return true; } } @@ -1323,7 +1323,7 @@ bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const Q */ bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin, ImportedNamespace** ns_return) const { - ImportedNamespace* ns = imports.d->findNamespace(QLatin1String(type)); + ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type)); if (ns) { if (qmlImportTrace()) qDebug() << "QmlEngine::resolveType" << type << "is namespace for" << ns->urls; diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 16129ee..e20616a 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -325,8 +325,8 @@ void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArra QString objectName = o->objectName(); if (objectName.isEmpty()) objectName = QLatin1String(""); - v = QLatin1String(o->metaObject()->className()) + - QLatin1String(": ") + objectName; + v = QString::fromUtf8(o->metaObject()->className()) + + QLatin1String(": ") + objectName; } if (v.isNull()) v = value.toString(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 0de64d9..76ca2c1 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -212,7 +212,7 @@ QString QmlExpression::expression() const { Q_D(const QmlExpression); if (d->data->sse.isValid()) - return QLatin1String(d->data->sse.expression()); + return QString::fromUtf8(d->data->sse.expression()); else return d->data->expression; } diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index bae1682..e3c0225 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -95,7 +95,7 @@ QmlInfo::QmlInfo(QObject *object) location += QLatin1String(":"); location += QString::number(ddata->columnNumber); location += QLatin1String(")"); - *this << location.toLatin1().constData(); + *this << qPrintable(location); } else { *this << "(unknown location):"; } diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp index 564faaa..89a18a1 100644 --- a/src/declarative/qml/qmlintegercache.cpp +++ b/src/declarative/qml/qmlintegercache.cpp @@ -87,7 +87,7 @@ QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engin QMetaEnum enumerator = mo->enumerator(ii); for (int jj = 0; jj < enumerator.keyCount(); ++jj) { - QString name = QLatin1String(enumerator.key(jj)); + QString name = QString::fromUtf8(enumerator.key(jj)); int value = enumerator.value(jj); if (!name.at(0).isUpper()) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 8643301..ce4836e 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -174,7 +174,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (typeData) { QmlType *t = 0; - enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0); + enginePrivate->resolveType(typeData->imports, name.toUtf8(), &t, 0, 0, 0, 0); if (t && t->attachedPropertiesFunction()) { attachedFunc = t->index(); } @@ -467,7 +467,7 @@ QStringList QmlMetaProperty::properties(QObject *obj) const QMetaObject *mo = obj->metaObject(); for (int ii = 0; ii < mo->propertyCount(); ++ii) { QMetaProperty prop = mo->property(ii); - rv << QLatin1String(prop.name()); + rv << QString::fromUtf8(prop.name()); } return rv; @@ -487,7 +487,7 @@ QString QmlMetaProperty::name() const else valueType = QmlValueTypeFactory::valueType(d->core.propType); Q_ASSERT(valueType); - rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); + rv += QString::fromUtf8(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); if (!ep) delete valueType; @@ -654,7 +654,7 @@ QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name int methods = mo->methodCount(); for (int ii = methods - 1; ii >= 0; --ii) { QMetaMethod method = mo->method(ii); - QString methodName = QLatin1String(method.signature()); + QString methodName = QString::fromUtf8(method.signature()); int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); @@ -837,7 +837,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data u = value.toUrl(); found = true; } else if (vt == QVariant::ByteArray) { - u = QUrl(QLatin1String(value.toByteArray())); + u = QUrl(QString::fromUtf8(value.toByteArray())); found = true; } else if (vt == QVariant::String) { u = QUrl(value.toString()); diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 41573a2..80f2786 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -267,7 +267,7 @@ QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngi if(obj){ QString objectName = obj->objectName(); - ret += QLatin1String(obj->metaObject()->className()); + ret += QString::fromUtf8(obj->metaObject()->className()); ret += QLatin1String("(0x"); ret += QString::number((quintptr)obj,16); diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 63ce00c..e00126f 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -52,7 +52,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) propType = qMetaTypeId(); coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); - name = QLatin1String(p.name()); + name = QString::fromUtf8(p.name()); if (p.isConstant()) flags |= Data::IsConstant; @@ -76,7 +76,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) void QmlPropertyCache::Data::load(const QMetaMethod &m) { - name = QLatin1String(m.signature()); + name = QString::fromUtf8(m.signature()); int parenIdx = name.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); name = name.left(parenIdx); @@ -120,7 +120,7 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); @@ -151,7 +151,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject cache->indexCache.resize(propCount); for (int ii = propCount - 1; ii >= 0; --ii) { QMetaProperty p = metaObject->property(ii); - QString propName = QLatin1String(p.name()); + QString propName = QString::fromUtf8(p.name()); RData *data = new RData; data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); @@ -172,7 +172,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 1c7bf83..57e40b6 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -87,12 +87,12 @@ class ProcessAST: protected AST::Visitor const State &state = top(); if (state.property) { State s(state.property->getValue(), - state.property->getValue()->getProperty(name.toLatin1())); + state.property->getValue()->getProperty(name.toUtf8())); s.property->location = location; push(s); } else { State s(state.object, - state.object->getProperty(name.toLatin1())); + state.object->getProperty(name.toUtf8())); s.property->location = location; push(s); @@ -312,7 +312,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, // XXX this doesn't do anything (_scope never builds up) _scope.append(resolvableObjectType); - obj->typeName = qualifiedNameId().toLatin1(); + obj->typeName = qualifiedNameId().toUtf8(); _scope.removeLast(); obj->location = location; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index d4921b6..675f5ae 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -515,7 +515,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, int sigIdx = instr.assignSignalObject.signal; const QByteArray &pr = datas.at(sigIdx); - QmlMetaProperty prop(target, QLatin1String(pr)); + QmlMetaProperty prop(target, QString::fromUtf8(pr)); if (prop.type() & QmlMetaProperty::SignalProperty) { QMetaMethod method = QmlMetaType::defaultMethod(assign); diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 247e64c..ed5018d 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -73,7 +73,7 @@ QEasingCurve stringToCurve(const QString &curve) QString easeName = curve.trimmed(); if (!easeName.endsWith(QLatin1Char(')'))) { qWarning("QEasingCurve: Unmatched perenthesis in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } @@ -83,7 +83,7 @@ QEasingCurve stringToCurve(const QString &curve) normalizedCurve = easeName.left(idx); if (!normalizedCurve.startsWith(QLatin1String("ease"))) { qWarning("QEasingCurve: Easing function '%s' must start with 'ease'", - curve.toLatin1().constData()); + qPrintable(curve)); } props = prop_str.split(QLatin1Char(',')); @@ -95,10 +95,10 @@ QEasingCurve stringToCurve(const QString &curve) static int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type"); static QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index); - int value = me.keyToValue(normalizedCurve.toLatin1().constData()); + int value = me.keyToValue(normalizedCurve.toUtf8().constData()); if (value < 0) { qWarning("QEasingCurve: Unknown easing curve '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); value = 0; } easingCurve.setType((QEasingCurve::Type)value); @@ -109,7 +109,7 @@ QEasingCurve stringToCurve(const QString &curve) if (sep == -1) { qWarning("QEasingCurve: Improperly specified property in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } @@ -119,7 +119,7 @@ QEasingCurve stringToCurve(const QString &curve) if (propName.isEmpty() || !isOk) { qWarning("QEasingCurve: Improperly specified property in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp index c77d0f6..2a7cf6c 100644 --- a/src/declarative/util/qmlconnection.cpp +++ b/src/declarative/util/qmlconnection.cpp @@ -163,7 +163,7 @@ void QmlConnection::connectIfValid() if (lparen >= 0 && d->signal.length() > lparen+2) { QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(',')); foreach (const QString &s, l) { - sigparams.append(s.toLatin1()); + sigparams.append(s.toUtf8()); } } QString signalname = d->signal.left(lparen); @@ -172,7 +172,7 @@ void QmlConnection::connectIfValid() int methods = mo->methodCount(); for (int ii = 0; ii < methods; ++ii) { QMetaMethod method = mo->method(ii); - QString methodName = QLatin1String(method.signature()); + QString methodName = QString::fromUtf8(method.signature()); int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) { diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 062ab48..4dc9bc5 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -233,7 +233,7 @@ struct ModelNode QHash::iterator it; for (it = properties.begin(); it != properties.end(); ++it) { if (!(*it)->values.isEmpty()) - objectCache->setValue(it.key().toLatin1(), (*it)->values.first()); + objectCache->setValue(it.key().toUtf8(), (*it)->values.first()); } } return objectCache; @@ -252,7 +252,7 @@ struct ModelNode properties.insert(prop,n); } if (objectCache) - objectCache->setValue(prop.toLatin1(), val); + objectCache->setValue(prop.toUtf8(), val); } QmlListModel *modelCache; @@ -709,7 +709,7 @@ bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QL qvariant_cast(value); int ref = data.count(); - QByteArray d = variant.asScript().toLatin1(); + QByteArray d = variant.asScript().toUtf8(); d.append('\0'); data.append(d); @@ -799,7 +799,7 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) { ModelNode *n = nodes.top(); ModelNode *n2 = new ModelNode; - n->properties.insert(QLatin1String(data + instr.dataIdx), n2); + n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2); nodes.push(n2); } break; -- cgit v0.12 From 7dba87c897d8723cc61093c1457cb5a7340f3b61 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 12 Oct 2009 13:05:43 +1000 Subject: Fix warnings. --- src/declarative/qml/qmlcompiler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 12e8101..670e442 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -809,7 +809,7 @@ void QmlCompiler::genObject(QmlParser::Object *obj) if (!obj->metadata.isEmpty()) { QmlInstruction meta; meta.type = QmlInstruction::StoreMetaObject; - meta.line = -1; + meta.line = 0; meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); @@ -822,7 +822,7 @@ void QmlCompiler::genObject(QmlParser::Object *obj) if (!obj->id.isEmpty()) { QmlInstruction id; id.type = QmlInstruction::SetId; - id.line = -1; + id.line = 0; id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; output->bytecode << id; @@ -832,7 +832,7 @@ void QmlCompiler::genObject(QmlParser::Object *obj) for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) { QmlInstruction script; script.type = QmlInstruction::StoreScript; - script.line = -1; // ### + script.line = 0; // ### script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); output->bytecode << script; } @@ -997,7 +997,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj) if (!obj->id.isEmpty()) { QmlInstruction id; id.type = QmlInstruction::SetId; - id.line = -1; + id.line = 0; id.setId.value = output->indexForString(obj->id); id.setId.index = obj->idIndex; output->bytecode << id; -- cgit v0.12 From 55e4d0591a2b18e08519144a416d1fea9a625cd8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 13:13:08 +1000 Subject: Use utf8 instead of latin1 where appropriate --- src/declarative/qml/qmlxmlhttprequest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index 0bc927c..5117a00 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -1105,7 +1105,7 @@ void QmlXMLHttpRequest::downloadProgress(qint64 bytes) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); // ### We assume if this is called the headers are now available if (m_state < HeadersReceived) { @@ -1127,7 +1127,7 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); m_responseEntityBody = QByteArray(); m_errorFlag = true; @@ -1146,7 +1146,7 @@ void QmlXMLHttpRequest::finished() m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); if (m_state < HeadersReceived) { m_state = HeadersReceived; -- cgit v0.12 From 1ea93870fce7ff032053775fb19d42e950dd5ccb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 13:58:42 +1000 Subject: Composite types should assign to object properties Fixes QT-956 --- src/declarative/qml/qmlcompileddata.cpp | 4 ++-- src/declarative/qml/qmlcompiler.cpp | 16 +++++++++++----- src/declarative/qml/qmlcompiler_p.h | 3 ++- src/declarative/qml/qmlengine.cpp | 6 +++--- src/declarative/qml/qmlmetaproperty.cpp | 13 +++++++++++-- src/declarative/qml/qmlmetaproperty_p.h | 2 ++ .../declarative/qmllanguage/data/CompositeType.qml | 4 ++++ .../declarative/qmllanguage/data/CompositeType2.qml | 5 +++++ .../declarative/qmllanguage/data/CompositeType3.qml | 5 +++++ .../declarative/qmllanguage/data/CompositeType4.qml | 6 ++++++ .../qmllanguage/data/assignCompositeToType.qml | 18 ++++++++++++++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 10 ++++++++++ 12 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/CompositeType.qml create mode 100644 tests/auto/declarative/qmllanguage/data/CompositeType2.qml create mode 100644 tests/auto/declarative/qmllanguage/data/CompositeType3.qml create mode 100644 tests/auto/declarative/qmllanguage/data/CompositeType4.qml create mode 100644 tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index 8c3c355..7032a3b 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -150,7 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l) } QmlCompiledData::QmlCompiledData() -: importCache(0) +: importCache(0), root(0) { } @@ -189,7 +189,7 @@ const QMetaObject *QmlCompiledData::TypeReference::metaObject() const return type->metaObject(); } else { Q_ASSERT(component); - return &static_cast(QObjectPrivate::get(component))->cc->root; + return static_cast(QObjectPrivate::get(component))->cc->root; } } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 48d3360..6d1df6d 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -647,7 +647,13 @@ void QmlCompiler::compileTree(Object *tree) output->importCache = output->imports.cache(engine); Q_ASSERT(tree->metatype); - static_cast(output->root) = *tree->metaObject(); + + if (tree->metadata.isEmpty()) { + output->root = tree->metatype; + } else { + static_cast(output->rootData) = *tree->metaObject(); + output->root = &output->rootData; + } if (!tree->metadata.isEmpty()) QmlEnginePrivate::get(engine)->registerCompositeType(output); } @@ -1905,7 +1911,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, if (propertyMetaObject) { const QMetaObject *c = v->object->metatype; while(c) { - isAssignable |= (c == propertyMetaObject); + isAssignable |= (QmlMetaPropertyPrivate::equal(c, propertyMetaObject)); c = c->superClass(); } } @@ -2101,7 +2107,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(tdata->status == QmlCompositeTypeData::Complete); QmlCompiledData *data = tdata->toCompiledComponent(engine); - customTypeName = data->root.className(); + customTypeName = data->root->className(); } else { customTypeName = qmltype->typeName(); } @@ -2473,7 +2479,7 @@ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) const QMetaObject *fromMo = from->metaObject(); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } @@ -2492,7 +2498,7 @@ bool QmlCompiler::canCoerce(int to, int from) QmlEnginePrivate::get(engine)->rawMetaObjectForType(from); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 3a35d58..ecf3344 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -104,7 +104,8 @@ public: int type; }; - QAbstractDynamicMetaObject root; + const QMetaObject *root; + QAbstractDynamicMetaObject rootData; QList primitives; QList floatData; QList intData; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index c644ccc..245ddc0 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -1379,7 +1379,7 @@ static void *voidptr_constructor(const void *v) void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data) { - QByteArray name = data->root.className(); + QByteArray name = data->root->className(); QByteArray ptr = name + "*"; QByteArray lst = "QmlList<" + ptr + ">*"; @@ -1417,7 +1417,7 @@ const QMetaObject *QmlEnginePrivate::rawMetaObjectForType(int t) const { QHash::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::rawMetaObjectForType(t); } @@ -1427,7 +1427,7 @@ const QMetaObject *QmlEnginePrivate::metaObjectForType(int t) const { QHash::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::metaObjectForType(t); } diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index ce4836e..34c98bf 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -874,7 +874,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t); while (valMo) { - if (valMo == propMo) + if (equal(valMo, propMo)) break; valMo = valMo->superClass(); } @@ -928,7 +928,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *objMo = obj->metaObject(); bool found = false; while(!found && objMo) { - if (objMo == mo) + if (equal(objMo, mo)) found = true; else objMo = objMo->superClass(); @@ -1211,4 +1211,13 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, return prop; } +/*! + Returns true if lhs and rhs refer to the same metaobject data +*/ +bool QmlMetaPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs) +{ + return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index b74aa2d..7288266 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -106,6 +106,8 @@ public: static quint32 saveValueType(int, int); static quint32 saveProperty(int); + + static bool equal(const QMetaObject *, const QMetaObject *); }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType.qml b/tests/auto/declarative/qmllanguage/data/CompositeType.qml new file mode 100644 index 0000000..8c5094b --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/CompositeType.qml @@ -0,0 +1,4 @@ +import Qt 4.6 + +Object { +} diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType2.qml b/tests/auto/declarative/qmllanguage/data/CompositeType2.qml new file mode 100644 index 0000000..86210e9 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/CompositeType2.qml @@ -0,0 +1,5 @@ +import Test 1.0 + +MyQmlObject { +} + diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType3.qml b/tests/auto/declarative/qmllanguage/data/CompositeType3.qml new file mode 100644 index 0000000..bb5469a --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/CompositeType3.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +Object { + property int a +} diff --git a/tests/auto/declarative/qmllanguage/data/CompositeType4.qml b/tests/auto/declarative/qmllanguage/data/CompositeType4.qml new file mode 100644 index 0000000..a6a8168 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/CompositeType4.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyQmlObject { + property int a +} + diff --git a/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml b/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml new file mode 100644 index 0000000..ec2867d --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/assignCompositeToType.qml @@ -0,0 +1,18 @@ +import Qt 4.6 +import Test 1.0 + +Object { + property Object myProperty + property Object myProperty2 + property Object myProperty3 + property Object myProperty4 + property MyQmlObject myProperty5 + property MyQmlObject myProperty6 + + myProperty: CompositeType {} + myProperty2: CompositeType2 {} + myProperty3: CompositeType3 {} + myProperty4: CompositeType4 {} + myProperty5: CompositeType2 {} + myProperty6: CompositeType4 {} +} diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index ff78e6d..94998c7 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -39,6 +39,7 @@ private slots: void assignQmlComponent(); void assignBasicTypes(); void assignTypeExtremes(); + void assignCompositeToType(); void customParserTypes(); void rootAsQmlComponent(); void inlineQmlComponents(); @@ -323,6 +324,15 @@ void tst_qmllanguage::assignTypeExtremes() QCOMPARE(object->intProperty(), -0x77359400); } +// Test that a composite type can assign to a property of its base type +void tst_qmllanguage::assignCompositeToType() +{ + QmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + // Tests that custom parser types can be instantiated void tst_qmllanguage::customParserTypes() { -- cgit v0.12 From 9094a6588de3a7264ec4647a24b94253a7609823 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 12 Oct 2009 14:07:22 +1000 Subject: More doc on data models. --- doc/src/declarative/qmlmodels.qdoc | 108 +++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc index eca81cd..4cc0e8b 100644 --- a/doc/src/declarative/qmlmodels.qdoc +++ b/doc/src/declarative/qmlmodels.qdoc @@ -71,14 +71,87 @@ or C++ (via QmlContext::setContextProperty(), for example). \section1 QML Data Models -\list -\o ListModel is a simple hierarchy of elements specified in QML. The +\section2 ListModel + +ListModel is a simple hierarchy of elements specified in QML. The available roles are specified by the \l ListElement properties. -\o XmlListModel allows construction of a model from an XML data source. The roles + +\code +ListModel { + id: fruitModel + ListElement { + name: "Apple" + cost: 2.45 + } + ListElement { + name: "Orange" + cost: 3.25 + } + ListElement { + name: "Banana" + cost: 1.95 + } +} +\endcode + +The above model has two roles, \e name and \e cost. These can be bound +bound to by a ListView delegate, for example: + +\code +Component { + id: fruitDelegate + Row { + Text { text: "Fruit: " + name } + Text { text: "Cost: $" + cost } + } +} +ListView { + model: fruitModel + delegate: fruitDelegate +} +\endcode + + +\section2 XmlListModel + +XmlListModel allows construction of a model from an XML data source. The roles are specified via the \l XmlRole element. -\o VisualItemModel allows QML items to be provided as a model. This model contains + +The following model has three roles, \e title, \e link and \e description: +\code +XmlListModel { + id: feedModel + source: "http://rss.news.yahoo.com/rss/oceania" + query: "/rss/channel/item" + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "link"; query: "link/string()" } + XmlRole { name: "description"; query: "description/string()" } +} +\endcode + + +\section2 VisualItemModel + +VisualItemModel allows QML items to be provided as a model. This model contains both the data and delegate (its child items). This model does not provide any roles. -\endlist + +\code + VisualItemModel { + id: itemModel + Rectangle { height: 30; width: 80; color: "red" } + Rectangle { height: 30; width: 80; color: "green" } + Rectangle { height: 30; width: 80; color: "blue" } + } + + ListView { + anchors.fill: parent + model: itemModel + } +\endcode + +Note that in the above example there is no delegate required. +The items of the model itself provide the visual elements that +will be positioned by the view. \section1 C++ Data Models @@ -92,11 +165,28 @@ both the data and delegate (its child items). This model does not provide any r \section1 Other Data Models -\list -\o An Integer specifies a model containing the integer number of elements. + +\section2 An Integer + +An Integer specifies a model containing the integer number of elements. There are no data roles. -\o An Object Instance specifies a model with a single Object element. The + +The following example creates a ListView with five elements: +\code +Component { + id: itemDelegate + Text { text: "I am item number: " + index } +} +ListView { + model: 5 + delegate: itemDelegate +} +\endcode + + +\section2 An Object Instance + +An Object Instance specifies a model with a single Object element. The properties of the object are provided as roles. -\endlist */ -- cgit v0.12 From 24653fc546fe8150ebca1c44c36fe17c36527cc7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 14:15:08 +1000 Subject: Test that Component {} is allowed as the root element --- src/declarative/qml/qmlcompiler.cpp | 6 ++++-- tests/auto/declarative/qmllanguage/data/ComponentComposite.qml | 5 +++++ .../declarative/qmllanguage/data/componentCompositeType.qml | 8 ++++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 10 ++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/ComponentComposite.qml create mode 100644 tests/auto/declarative/qmllanguage/data/componentCompositeType.qml diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 6d1df6d..023903d 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -672,7 +672,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) obj->className = tr.className; // This object is a "Component" element - if (obj->metatype == &QmlComponent::staticMetaObject) { + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { COMPILE_CHECK(buildComponent(obj, ctxt)); return true; } @@ -786,7 +786,9 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) void QmlCompiler::genObject(QmlParser::Object *obj) { - if (obj->metatype == &QmlComponent::staticMetaObject) { + const QmlCompiledData::TypeReference &tr = + output->types.at(obj->type); + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { genComponent(obj); return; } diff --git a/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml b/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml new file mode 100644 index 0000000..f8726ef --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/ComponentComposite.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +Component { + Object {} +} diff --git a/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml b/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml new file mode 100644 index 0000000..3a1b191 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/componentCompositeType.qml @@ -0,0 +1,8 @@ +import Qt 4.6 + +Object { + property var test + + test: ComponentComposite {} +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 94998c7..a991144 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -57,6 +57,7 @@ private slots: void valueTypes(); void cppnamespace(); void aliasProperties(); + void componentCompositeType(); void importsBuiltin_data(); void importsBuiltin(); @@ -657,6 +658,15 @@ void tst_qmllanguage::aliasProperties() } } +// Test that the root element in a composite type can be a Component +void tst_qmllanguage::componentCompositeType() +{ + QmlComponent component(&engine, TEST_FILE("componentCompositeType.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); +} + class TestType : public QObject { Q_OBJECT public: -- cgit v0.12 From 9c60045b13dec0faf858b922ed6121c0b06483c5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 15:02:42 +1000 Subject: Doc --- doc/src/declarative/extending.qdoc | 62 ++- doc/src/declarative/qmlforcpp.qdoc | 713 --------------------------------- doc/src/declarative/qtdeclarative.qdoc | 1 - 3 files changed, 59 insertions(+), 717 deletions(-) delete mode 100644 doc/src/declarative/qmlforcpp.qdoc diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index bc18108..db35961 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -511,6 +511,18 @@ to be used in bindings should have a NOTIFY signal instead. \l {Extending QML - Binding Example} shows the BirthdayParty example updated to include NOTIFY signals for use in binding. +\section1 Binding and Script Properties + +While generally no changes are needed to a C++ class to use property +binding, sometimes more advanced interaction between the binding engine and +an object is desirable. To facilitate this, there is a special exception +in the bind engine for allowing an object to access the binding directly. + +If a binding is assigned to a property with a type of QmlBinding +pointer (ie. \c {QmlBinding *}), each time the binding value changes, +a QmlBinding instance is assigned to that property. The QmlBinding instance +allows the object to read the binding and to evaluate the binding's current value. + \section1 Extension Objects \snippet examples/declarative/extending/extended/example.qml 0 @@ -522,15 +534,59 @@ When integrating existing classes and technology into QML, their APIs will often need to be tweaked to fit better into the declarative environment. Although the best results are usually obtained by modifying the original classes directly, if this is either not possible or is complicated by some other -concerns extension objects allow limited extension possibilities without +concerns, extension objects allow limited extension possibilities without direct modifications. -Extension objects can only add properties. +Extension objects are used to add additional properties to an existing type. +Extension objects can only add properties, not signals or methods. An extended +type definition allows the programmer to supply an additional type - known as the +extension type - when registering the target class whose properties are +transparently merged with the original target class when used from within QML. + +An extension class is a regular QObject, with a constructor that takes a QObject +pointer. When needed (extension classes are delay created until the first extended +property is accessed) the extension class is created and the target object is +passed in as the parent. When an extended property on the original is accessed, +the appropriate property on the extension object is used instead. + +When an extended type is installed, one of the +\code + #define QML_DEFINE_EXTENDED_TYPE(URI, VMAJ, VFROM, VTO, QmlName,T, ExtendedT) + #define QML_DEFINE_EXTENDED_NOCREATE_TYPE(T, ExtendedT) +\endcode +macros should be used instead of the regular \c QML_DEFINE_TYPE or +\c QML_DEFINE_NOCREATE_TYPE. The arguments are identical to the corresponding +non-extension object macro, except for the ExtendedT parameter which is the type +of the extension object. \section1 Optimization -*/ +Often to develop high performance elements it is helpful to know more about the +status of the QML engine. For example, it might be beneficial to delay +initializing some costly data structures until after all the properties have been +set. +The QML engine defines an interface class called QmlParserStatus, which contains a +number of virtual methods that are invoked at various stages during component +instantiation. To receive these notifications, an element implementation inherits +QmlParserStatus and notifies the Qt meta system using the Q_INTERFACES() macro. + +For example, + +\code +class Example : public QObject, public QmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QmlParserStatus) +public: + virtual void componentComplete() + { + qDebug() << "Woohoo! Now to do my costly initialization"; + } +}; +\endcode + +*/ /*! \page qml-extending-types.html diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc deleted file mode 100644 index 5378571..0000000 --- a/doc/src/declarative/qmlforcpp.qdoc +++ /dev/null @@ -1,713 +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 documentation 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$ -** -****************************************************************************/ - -/*! - \page qmlforcpp.html - \target qmlforcpp - \title QML for C++ Programmers - - This page describes the QML format and how to use and extend it from C++. - - The QML syntax declaratively describes how to construct an in memory - object tree. QML is usually used to describe a visual scene graph - but it is not conceptually limited to this: the QML format is an abstract - description of \bold any object tree. - - QML also includes property bindings. Bindings are ECMAScript expressions - of a properties value. Whenever the value of the expression changes - - either for the first time at startup or subsequently thereafter - the - property is automatically updated with the new value. - - \tableofcontents - - \section1 Loading and using QML Files - - QmlComponent is used to load a QML file and to create object instances. - - In QML a component is the unit of instantiation, and the most basic unit - of scope. A component is like a template for how to construct an object - tree. One component can create multiple instances of this tree, but the - template remains constant. - - The following code uses the C++ interface to create 100 red rectangles - based on a simple declarative component description. - - \code - QmlEngine engine; - QmlComponent redRectangle(&engine, "Rectangle { color: \"red\"; width: 100; height: 100 }"); - for (int ii = 0; ii < 100; ++ii) { - QObject *rectangle = redRectangle.create(); - // ... do something with the rectangle ... - } - \endcode - - Each independent file describes a QML component, but it is also possible to - create sub-components within a QML file as will be shown later. - - \section1 QML Format 101 - - This is some sample QML code. - - \code - Image { - id: myRect - x: 10 - y: 10 - width: 100 - height: 100 - source: "background.png" - - Text { - height: 50 - width: 100 - color: "white" - font.fontSize: 16 - text: "Hello world!" - } - } - \endcode - - The QML snippet shown above instantiates one \c Image instance and one - \c Text instance and sets properties on both. \bold Everything in QML - ultimately comes down to either instantiating an object instance, or - assigning a property a value. QML relies heavily on Qt's meta object system - and can only instantiate classes that derive from QObject. - - In the above example, each property is placed on its own line. You can - also place multiple properties on one line by separating them with a - semi-colon. The code below is equivalent to the example above. - - \code - Image { - id: myRect - x: 10; y: 10; width: 100; height: 100 - source: "background.png" - Text { height: 50; width: 100; color: "white"; font.fontSize: 16; text: "Hello world!" } - } - \endcode - - QML can set properties that are more complex than just simple types like - integers and strings. Properties can be object pointers or Qt interface - pointers or even lists of object or Qt interface pointers! QML is typesafe, - and will ensure that only the valid types are assigned to properties. - - Assigning an object to a property is as simple as assigning a basic - integer. Attempting to assign an object to a property when type coercian - fails will produce an error. The following shows an example of valid and of - invalid QML and the corresponding C++ classes. - - \table - \row \o - \code - class Image : public QObject - { - ... - Q_PROPERTY(ImageFilter *filter READ filter WRITE setFilter) - }; - - class ImageFilter : public QObject - { - ... - }; - \endcode - \o \code - // OK - Image { - filter: ImageFilter {} - } - - // NOT OK: Image cannot be cast into ImageFilter - Image { - filter: Image {} - } - \endcode - \endtable - - Classes can also define an optional default property. The default property - is used for assignment if no explicit property has been specified. - Any object property can be the default, even complex properties like lists - of objects. The default property of the \c Rect class is the \c children - property, a list of \c Item's. In the following example, as both \c Image - and \c Text inherit from \c Item the \c Image and \c Text instances are - added to the parent's \c children property. - - \code - Rectangle { - Image {} - Text {} - } - \endcode - - Properties that return read-only object pointers can be used recursively. - This can be used, for example, to group properties together. The - \c Text element has a \c font property that returns an object with a number - of sub-properties such as \c family, \c bold, \c italic and \c size. - QML makes it easy to interact with these grouped properties, as the - following shows - everything you would expect to work, just does. - - \table - \row \o - \code - class Text : public ... - { - ... - Q_PROPERTY(Font *font READ font); - }; - class Font : public QObject - { - ... - Q_PROPERTY(QString family READ family WRITE setFamily); - Q_PROPERTY(bool bold READ bold WRITE setBold); - Q_PROPERTY(bool italic READ italic WRITE setItalic); - Q_PROPERTY(int size READ size WRITE setSize); - }; - \endcode - \o - \code - Text { - font.family: "helvetica" - font.pointSize: 12 - font { - bold: true - italic: true - } - } - \endcode - \endtable - - \section1 Defining QML Types - - The QML engine has no intrinsic knowledge of any class types. Instead - the programmer must define the C++ types, their corresponding QML - name, library namespace, and version availability. - - \code - #define QML_DECLARE_TYPE(T) - #define QML_DEFINE_TYPE(URI,VMAJ,VFROM,VTO,QmlName,T) - \endcode - - Adding these macros to your library or executable automatically makes the - C++ type \a T available from the declarative markup language under the - name \a QmlName. Of course there's nothing stopping you using the same - name for both the C++ and the QML name! - Any type can be added to the QML engine using these macros. The only - requirements are that \a T inherits QObject, is not abstract, - and that it has a default constructor. - - \section1 Property Binding - - Assigning constant values and trees to properties will only get you so - far. Property binding allows a property's value to be dependant on the - value of other properties and data. Whenever these dependencies change, - the property's value is automatically updated. - - Property bindings are ECMAScript expressions and can be applied to any - object property. C++ classes don't have to do anything special to get - binding support other than define appropriate properties. When a non-literal - property assignment appears in a QML file, it is automatically treated as a - property binding. - - Here's a simple example that stacks a red, blue and green rectangle. - Bindings are used to ensure that the height of each is kept equal to it's - parent's. Were the root rectangle's height property to change, the child - rectangles height would be updated automatically. - - \code - Rectangle { - color: "red" - width: 100 - Rectangle { - color: "blue" - width: 50 - height: parent.height - Rectangle { - color: "green" - width: 25 - height: parent.height - } - } - } - \endcode - - Binding expressions execute in a context. A context behaves as a scope and - defines how the expression resolves property and variable names. Although - the two expressions in the last example are the same, the value of \c parent - resolves differently because each executes in a different context. Although - QML generally takes care of everything for the programmer, a thorough - understanding of bind contexts is important in some of the more complex QML - structures. - - Every expression is executed in a bind context, encapsulated by the - QmlContext C++ class. As covered in the class documentation, a - bind context contains a map of names to values, and a list of default - objects. When resolving a name, the name to value map is searched first. - If the name cannot be found, the default object's are iterated in turn and - the context attempts to resolve the name as a property of one of the default - objects. - - There are generally two contexts involved in the execution of a binding. - The first is the "object context" - a bind context associated with the - closest instantiated object and containing just one default object, and - that's instantiated object itself. The effect of the object - context is pretty simple - names in the binding expression resolve to - properties on the object first. It is important to note - particularly in - the case of grouped properties - the object context is that of the - instantiated object, the consequences of which are shown below. - - \code - // OK // NOT OK - Text { Text { - font { font { - bold: font.italic bold: italic - } } - } } - \endcode - - The second context is the "component context". Each QML component (and - consequently each QML file) is created in its own unique binding context. - Like the object context, the component context contains just one default - object - but in this case it is the component's root object. An example - will illustrate best - the resultant text will read "background.png". - - \code - Image { - source: "background.png" - Text { - text: source - } - } - \endcode - - If the name is not found in either of these contexts, the context heirarchy - is searched parent-by-parent until the name is either found, or the - heirarchy is exhausted. - - The first property binding example shown involved fixing the height of three - rectangles. It did this by fixing the height of each rectangle to its - parent, rather than fixing them all to a single common point. Here's the - example rewritten to do just that. - - \code - Rectangle { - color: "red" - width: 100 - Rectangle { - color: "blue" - width: 50 - height: parent.height - Rectangle { - color: "green" - width: 25 - height: parent.parent.height - } - } - } - \endcode - - Clearly this sort of fragile relationship is undesirable and unmanageable - - moving the green rectangle to be a sibling of the blue or introducing a - further rectangle between the two would break the example. - - To address this problem, QML includes a way to directly reference any object - within a component (or parent component for that matter), called "ids". - Developers assign an object an id, and can then reference it directly by - name. Developers assign an object an id by setting the special \c id - property. Every object automatically has this magical property (if the - object also has an actual property called \c id, that gets set too). As - an id allows an object to be referenced directly, it must be unique within - a component. By convention, id's should start with an uppercase letter. - - \code - Rectangle { - id: root - color: "red" - width: greenRect.width + 75 - height: root.height - Rectangle { - color: "blue" - width: greenRect.width + 25 - Rectangle { - id: greenRect - color: "green" - width: 25 - height: root.height - } - } - } - \endcode - - To relate id's back to QmlContext, id's exist as properties on the - component context. - - Bind expressions can reference any object property. The QML bind engine - relies on the presence of the NOTIFY signal in the Q_PROPERTY declaration - on a class to alert it that a property's value has changed. If this is - omitted, the bind expression can still access the property's value, but - the expression will not be updated if the value changes. The following is - an example of a QML friendly property declaration. - - \code - class Example : public QObject - { - Q_OBJECT - Q_PROPERTY(int sample READ sample WRITE setSample NOTIFY sampleChanged) - public: - int sample() const; - void setSample(int); - signals: - void sampleChanged(int); - }; - \endcode - - While generally no changes are needed to a C++ class to use property - binding, sometimes more advanced interaction between the binding engine and - an object is desirable. To facilitate this, there is a special exception - in the bind engine for allowing an object to access the binding directly. - - If a binding is assigned to a property with a type of QmlBindableValue - pointer (ie. QmlBindableValue *), each time the binding value changes, - a QmlBindableValue instance is assigned to that property. The - QmlBindableValue instance allows the object to read the binding and to - evaluate the binding's current value. - - \section1 Signal Properties - - In addition to reading and writing regular properties, QML allows you to - easily associate ECMAScript with signals. Consider the following example, - in which Button is a made-up type with a clicked() signal. - - \code - Button { - text: "Hello world!" - onClicked: print(text) - } - \endcode - - Clicking on the button causes "Hello world!" to be printed to the console - (or lost forever if you're running Windows). - - Like properties, signals automatically become available in QML without - any additional work. As illustrated signals are mapped into QML as special - "signal properties", using the name "on" where the first - character of the signal's name is uppercased. If more than one signal of - the same name is exist on a class, only the first is available (see the - \l Connection element for more general signal connections). - - An important observation to make here is the lack of braces. While both - property bindings and signal properties involve executing ECMAScript code, - property bindings dynamically update the property value (hence the braces), - whereas with signal properties the constant script "value" is actually - assigned to the signal property. Trying to bind a value to a signal - property will not work! - - Signal parameters are also available to the executing script, as shown - below, as long as you remember to name the parameters of your signal - in C++ (see QMetaMethod::parameterNames()). - - \table - \row \o - \code - Example { - onDoSomething: for(var ii = 0; ii < count; ++ii) - print(message) - } - \endcode - \o - \code - class Example : public QObject - { - Q_OBJECT - signals: - void doSomething(int count, const QString &message); - }; - \endcode - \endtable - - Just like property bindings, signal scripts are executed in a context. The - signal script context is identical in scope to the "object context" under - property binding, with the exception that it has the signal parameters - bound in. - - In addition to scripts, it is possible to assign objects to signal properties. - This automatically connects the signal to the object's default method. A - default method is defined just like a default property, though the special - "DefaultMethod" class info. - - \code - Q_CLASSINFO("DefaultMethod", "myMethod(int)"); - \endcode - - This is useful in achieving several use cases, like that below which moves - the button when it is clicked. - - \code - Button { - id: myButton - onClicked: NumberAnimation { - target: myButton - property: "x" - to: 100 - } - } - \endcode - - If the class itself actually defines a property called "on", this will - be assigned the string value and the signal handling behaviour will be - disabled. - - \section1 Attached Properties - - Attached properties allow unrelated types to annotate another type with some - additional properties. Some APIs or operations are inherintly imperative, - and attached properties help out when translating these APIs into the - declarative QML language. - - Qt's QGridLayout is one such example. - - \code - QGridLayout { - QLabel { - QGridLayout.row: 0 - QGridLayout.column: 0 - text: "Name:" - } - QLineEdit { - QGridLayout.row: 0 - QGridLayout.column: 1 - } - - QLabel { - QGridLayout.row: 1 - QGridLayout.column: 0 - text: "Occupation:" - } - QLineEdit { - QGridLayout.row: 1 - QGridLayout.column: 1 - } - } - \endcode - - Attached properties are identified by the use of a type name, in the - case shown \c QGridLayout, as a grouped property specifier. To prevent - ambiguity with actual class instantiations, attached properties must - always be specified to include a period but can otherwise be used just like - regular properties. - - C++ types provide attached properties by declaring the public function \c qmlAttachedProperties like this example. - - \table - \row \o - \code - static QObject *Type::qmlAttachedProperties(QObject *); - \endcode - \o - \code - class Example : public QObject - { - Q_OBJECT - public: - static QObject *qmlAttachedProperties(QObject *); - }; - \endcode - \endtable - - When an attached property is accessed, the QML engine will call this method - to create an attachment object, passing in the object instance that the - attached property applies to. The attachment object should define all - the attached properties, and is generally parented to the provided object - instance to avoid memory leaks. The QML engine does not saves this object, - so it is not necessary for the attached property function to ensure that - multiple calls for the same instance object return the same attached object. - - While conceptually simple, implementing an attachment object is not quite - so easy. The \c qmlAttachedProperties function is static - attachment - objects are not associated with any particular instance. How the values - of the attached properties apply to the behaviour they are controlling is - entirely implementation dependent. An additional consequence of this is - that \bold any object can attach \bold any attached property. The following is - perfectly valid, although the attached property has no actual effect: - - \code - FancyGridLayout { - Item { - Button { - QGridLayout.row: 1 - } - } - } - \endcode - - The property has no effect because the (made-up) FancyGridLayout type defines the meaning - of the \c row attached property only to apply to its direct children. It - is possible that other types may have attached properties that affect - objects that aren't their direct children. - - Attached properties are an advanced feature that should be used with - caution. - - \note We may implement a convenience wrapper that makes using attached - properties easier for the common "attach to children" case. - - \section1 Property Value Sources - - Intrinsically, the QML engine can assign a property either a static value, - such as a number or an object tree, or a property binding. It is possible for - advanced users to extend the engine to assign other "types" of values to - properties. These "types" are known as property value sources. - - Consider the following example. - - \code - Rectangle { - x: NumberAnimation { running: true; repeat; true; from: 0; to: 100; } - } - \endcode - - Here the \c x property of the rectangle will be animated from 0 to 100. - To support this, the NumberAnimation class inherits the - QmlPropertyValueSource class. If a type inherits this class and is assigned - to a property for which type assignment would otherwise fail (ie. the - property itself doesn't have a type of QmlPropertyValueSource *), the QML - engine will automatically set the property as the target of the value - source. - - \section1 Parser Status - - Generally using QML is a breeze - you implement your classes in C++, add - the appropriate properties, signals and slots and off you go. The QML - engine takes care of instantiating your classes and setting the properties - and everything works fine. - - However, sometimes it is helpful to know a little more about the status of - the QML parser. For example, it might be beneficial from a performance - standpoint to delay initializing some data structures until all the - properties have been set. - - To assist with this, the QML engine defines an interface class called - QmlParserStatus. The interface defines a number of virtual methods that are - invoked at various stages of the component instantiation. To receive - these notifications, all a class has to do is to inherit the interface, and - notify the Qt meta system using the Q_INTERFACES() macro. For example, - - \code - class Example : public QObject, public QmlParserStatus - { - Q_OBJECT - Q_INTERFACES(QmlParserStatus) - public: - virtual void componentComplete() - { - qDebug() << "Woohoo! Now to do my costly initialization"; - } - }; - \endcode - - \section1 Extended Type Definitions - - QML requires that types have the appropriate properties and signals to - work well within the declarative environment. In the case of existing - types, it is sometimes necessary to add signals, properties or slots to a - target class to make it more QML friendly but the original type cannot be - modified. For these cases, the QML engine supports extended type - definitions. - - An extended type definition allows the programmer to supply an additional - type - known as the extension type - when registering the target class - whose properties, signals and slots are transparently merged with the - original target class when used from within QML. - - An extension class is a regular QObject, with a constructor that takes a - QObject pointer. When needed (extension classes are delay created - until the first extension attribute is accessed) the extension - class is created and the target object is passed in as the parent. When - an extension attribute on the original is accessed, the appropriate signal, - property or slots on the extension object is used instead. - - When an extended type is installed, the - \code - #define QML_DEFINE_EXTENDED_TYPE(T,QmlName,ExtendedTypeName) - \endcode - macro should be used instead of the regular \c QML_DEFINE_TYPE. - - This example shows the addition of a read-only \c textLength property to - QLabel being implemented as an extension. - - \table - \row - \o - \code - class QLabelExtension : public QObject - { - Q_OBJECT - Q_PROPERTY(int textLength READ textLength) - public: - QWidgetExtension(QObject *parent) : QObject(parent) {} - int textLength() const { - return static_cast(parent())->text().count(); - } - }; - QML_DEFINE_EXTENDED_TYPE(QLabel,QLabel,QLabelExtension); - \endcode - \o - \code - QLabel { - id: label1 - text: "Hello World!" - } - QLabel { - text: "label1 text length: " + label1.textLength - } - \endcode - \endtable - - Attributes defined through extensions are inherited, just like attributes - defined on a normal class. Any types that inherit from \c QLabel, will - also have the \c textLength property. Derived types can include additional - extensions which are merged together, but only a single extension can be - specified for each single C++ class. - - Extended type definitions can even be used to add an attached properties - function to a type - just declare the \c qmlAttachedProperties function on - the extension object. - -*/ - diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index 1a13049..aeaa76e 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -67,7 +67,6 @@ \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} \o \l {qmlexamples}{Examples} - \o \l {qmlforcpp}{QML For C++ Programmers} \endlist Core QML Features: -- cgit v0.12 From a5c919183d9f52f3198b1b307ea75dab33ee4e1b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 15:04:08 +1000 Subject: Doc --- doc/src/declarative/qtdeclarative.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index aeaa76e..f7968b3 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -45,7 +45,7 @@ \ingroup modules \brief The Qt Declarative module provides a declarative framework for building - highly dynamic and fluid applications. + highly dynamic, custom UIs Qt Declarative is targetted at the sorts of user interface (and the sorts of hardware) in embedded devices such as phones, media -- cgit v0.12 From 3f86ef45fbde6a49dd3e6a8904d15cc0983d130d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 15:14:47 +1000 Subject: Doc --- doc/src/declarative/cppitem.qdoc | 170 --------------------------------- doc/src/declarative/qtdeclarative.qdoc | 1 - doc/src/declarative/qtprogrammers.qdoc | 3 +- 3 files changed, 1 insertion(+), 173 deletions(-) delete mode 100644 doc/src/declarative/cppitem.qdoc diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc deleted file mode 100644 index c5ef4c4..0000000 --- a/doc/src/declarative/cppitem.qdoc +++ /dev/null @@ -1,170 +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 documentation 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$ -** -****************************************************************************/ - -/*! -\page cppitem.html -\target cppitem -\title C++ Components for QML - -\section1 Making a C++ object available in QML - -In QML, the item types and properties correspond to Qt objects and properties. Thus, any Qt object -can potentially be used as an item in QML. More specifically, to make an object available in QML, -it should: -\list -\o Be a subclass of QObject. -\o Provide a default constructor. -\o Declare Q_PROPERTYs. -\o Be registered via the QML_DECLARE_TYPE and QML_DEFINE_TYPE macros. -\endlist - -\section2 Declaring Q_PROPERTYs -\target properties - -Properties of QObject subclasses are available as properties in QML. -Like any QObject, these properties are defined by the Q_PROPERTY -macro in the header file. - -Properties should have a NOTIFY function if they can change dynamically and -if any useful response could be made to them changing in another object. Almost -all properties will thus need a NOTIFY function. - -\code - Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged); - qreal scale() const; - void setScale(qreal); - ... - signals: void scaleChanged(); -\endcode - -The property types currently supported by QML are: -\list -\o int -\o qreal -\o QString -\o QColor -\o QDate, QTime, and QDateTime -\o QSize and QSizeF -\o QPoint and QPointF -\o QRect and QRectF -\o QPixmap -\o QIcon -\o enums registered with Q_ENUMS -\o flags registered with Q_FLAGS -\o QVariant -\o QObject* (or subclass) -\endlist - -Custom property types that provide string-to-type conversion can be used as well, by: -\list -\o Registering them as a metatype (Q_DECLARE_METATYPE() and qRegisterMetaType()) -\o Registering a string-to-type convertor function (QML::addCustomStringConvertor()). -\endlist - -\section2 Registering your type -\target register - -In order for your type to be usable in QML, you must register it: - -\code -QML_DECLARE_TYPE(TypeName); -QML_DEFINE_TYPE(ModuleUri,ModuleMajorVersion,ModuleMinorVersionFrom,ModuleMinorVersionTo,QmlName,TypeName); -\endcode - -These macros make the C++ \e TypeName available from the declarative markup language under the name \e QmlName. -Of course there's nothing stopping you using the same name for both the C++ and the QML name! - -For example: -\code -QML_DECLARE_TYPE(MyCircle); -QML_DEFINE_TYPE(MyLib,1,0,5,Circle,MyCircle); -\endcode -would make the \e MyCircle class accessable though the \c Circle type in QML whenever MyLib 1.0 to 1.5 is imported. - - -\section1 Creating a new type of QML item in C++ - -You can create a new type of QML item by: -\list 1 -\o Creating a subclass of QFxItem, -\o Adding Q_PROPERTYs appropriate for your item (see \l {properties}{Properties}), -\o Reimplementing the relevant paint functions, -\o Registering the type with the QML_DECLARE_TYPE and QML_DEFINE_TYPE macros (see \l {register}{Register}). -\endlist - -\section2 Creating a subclass of QFxItem - -To add a new type, you first must add a new C++ class derived from QFxItem. -You may of course extend existing QFxItem subclasses. - -One existing subclass is QFxPaintedItem, which provides -a simple cached-image painting model. - -\section2 Reimplementing paint functions - -\warning This section is out of date. Use the normal QGraphicsItem::paint function. - -Two alternative painters are available, offering -different levels of performance and functionality: -QPainter, GLPainter. - -You can choose to subclass QFxPaintedItem rather than QFxItem, -and then implement the virtual method: - -\code - void drawContents(QPainter *painter, const QRect &rect); -\endcode - -This paints into an offscreen pixmap which is then painted to the display (transformed, -etc. as needed). The cost of this offscreen pixmap should be carefully considered, as -should the specific performance of the painting done in the paint function. - -If you require more control, subclass QFxItem instead. -QFxItem subclasses must implement both simple software canvas painting -and GL painting: -\list -\o \c QFxItem::paintContents(QPainter &) for the simple software canvas, -\o \c QFxItem::paintGLContents(GLPainter &) for OpenGL. -\endlist - -See the documentation of those functions for detailed subclassing notes. - -*/ diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index f7968b3..aa0ff7f 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -90,6 +90,5 @@ \list \o \l {Extending QML} \o \l {qtbinding}{QML/C++ Data Binding} - \o \l {cppitem}{C++ Components} \endlist */ diff --git a/doc/src/declarative/qtprogrammers.qdoc b/doc/src/declarative/qtprogrammers.qdoc index 00c2d48..ea27d7e 100644 --- a/doc/src/declarative/qtprogrammers.qdoc +++ b/doc/src/declarative/qtprogrammers.qdoc @@ -65,8 +65,7 @@ QML provides direct access to the following concepts from Qt: \o Qt models - used directly in data binding (QAbstractItemModel and next generation QListModelInterface) \endlist -Qt knowledge is \e required for \l {cppitem}{writing elements in C++}. - +Qt knowledge is \e required for \l {Extending QML}. \section1 QML Items compared with QWidgets -- cgit v0.12 From 0241f0e132ef9724876d62cf3a4c29e7fa10cd6d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 15:34:30 +1000 Subject: Doc --- src/declarative/extra/qfxparticles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/extra/qfxparticles.cpp b/src/declarative/extra/qfxparticles.cpp index b4a04a9..36fdd79 100644 --- a/src/declarative/extra/qfxparticles.cpp +++ b/src/declarative/extra/qfxparticles.cpp @@ -111,6 +111,7 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,ParticleMotion,QFxParticleMotion \class QFxParticleMotion \ingroup group_effects \brief The QFxParticleMotion class is the base class for particle motion. + \internal This class causes the particles to remain static. */ -- cgit v0.12 From ce37daea42e85a62bebff56fabe7103cd54df288 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 15:47:36 +1000 Subject: Doc --- doc/src/declarative/binding.qdoc | 8 +++++--- doc/src/declarative/qtdeclarative.qdoc | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc index 4f9bdc8..79ba6ac 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/binding.qdoc @@ -41,10 +41,12 @@ /*! \page binding.html -\title Data Binding in QML -\target binding +\title Property Binding -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. +Property binding is a declarative way of specifying the value of a property. Binding allows +a property's value to be expressed as an ECMAScript expression that defines the value relative +to other property values or data accessible in the application. The property value is +automatically kept up to date if the other properties or data values change. Bindings are created in QML when an expression is assigned to a property. For example, the following produces two rectangles of equal size (\c rect2 is bound to the size of \c rect1): \code diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index aa0ff7f..d60f4ed 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -71,7 +71,7 @@ Core QML Features: \list - \o \l {binding}{Data Binding} + \o \l {Property Binding} \o \l {qmlmodels}{Data Models} \o \l {anchor-layout}{Anchor-based Layout} \o \l {qmlanimation}{Animation} -- cgit v0.12 From b30731cea6f99ed3f2d358399f57fe3eb5739c17 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 16:11:56 +1000 Subject: Pass all WriteProperty args --- src/declarative/qml/qmlmetaproperty.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 34c98bf..79022e7 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -847,9 +847,9 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (found) { if (context && u.isRelative() && !u.isEmpty()) u = context->baseUrl().resolved(u); - void *a[1]; - a[0] = &u; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + int status = -1; + void *argv[] = { &u, 0, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); } } else if (vt == t) { -- cgit v0.12 From 949e21cdafeec0c0e4ac632ebbf21767479f04e5 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Mon, 12 Oct 2009 16:29:55 +1000 Subject: use aliases when possible --- examples/declarative/border-image/MyBorderImage.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/declarative/border-image/MyBorderImage.qml b/examples/declarative/border-image/MyBorderImage.qml index d64bfb2..9eb1270 100644 --- a/examples/declarative/border-image/MyBorderImage.qml +++ b/examples/declarative/border-image/MyBorderImage.qml @@ -1,9 +1,10 @@ import Qt 4.6 Item { - property var horizontalMode : BorderImage.Stretch - property var verticalMode : BorderImage.Stretch + property alias horizontalMode: image.horizontalTileMode + property alias verticalMode: image.verticalTileMode property alias source: image.source + property int minWidth property int minHeight property int maxWidth @@ -12,6 +13,7 @@ Item { id: container width: 240; height: 240 + BorderImage { id: image; x: container.width / 2 - width / 2; y: container.height / 2 - height / 2 @@ -27,8 +29,6 @@ Item { NumberAnimation { from: container.maxHeight; to: container.minHeight; duration: 2000; easing: "easeInOutQuad" } } - horizontalTileMode: container.horizontalMode - verticalTileMode: container.verticalMode border.top: container.margin border.left: container.margin border.bottom: container.margin -- cgit v0.12 From a6b0e516f6206133647317c3c54d9bfc8c040162 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 12 Oct 2009 17:12:31 +1000 Subject: I18n tests --- tests/auto/declarative/qmllanguage/data/I18n.qml | 6 ++++++ .../data/I18n\303\201\303\242\303\243\303\244\303\245.qml" | 4 ++++ .../qmllanguage/data/i18nDeclaredPropertyNames.qml | 6 ++++++ .../declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml | 5 +++++ tests/auto/declarative/qmllanguage/data/i18nScript.qml | 12 ++++++++++++ tests/auto/declarative/qmllanguage/data/i18nStrings.qml | 5 +++++ tests/auto/declarative/qmllanguage/data/i18nType.qml | 5 +++++ 7 files changed, 43 insertions(+) create mode 100644 tests/auto/declarative/qmllanguage/data/I18n.qml create mode 100644 "tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" create mode 100644 tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml create mode 100644 tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml create mode 100644 tests/auto/declarative/qmllanguage/data/i18nScript.qml create mode 100644 tests/auto/declarative/qmllanguage/data/i18nStrings.qml create mode 100644 tests/auto/declarative/qmllanguage/data/i18nType.qml diff --git a/tests/auto/declarative/qmllanguage/data/I18n.qml b/tests/auto/declarative/qmllanguage/data/I18n.qml new file mode 100644 index 0000000..dbbd4bd --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/I18n.qml @@ -0,0 +1,6 @@ +import Qt 4.6 + +Text { + property int áâãäå: 10 + text: "Test áâãäå: " + áâãäå +} diff --git "a/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" "b/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" new file mode 100644 index 0000000..6a841d1 --- /dev/null +++ "b/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" @@ -0,0 +1,4 @@ +import Qt 4.6 + +Text { +} diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml new file mode 100644 index 0000000..dbbd4bd --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml @@ -0,0 +1,6 @@ +import Qt 4.6 + +Text { + property int áâãäå: 10 + text: "Test áâãäå: " + áâãäå +} diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml new file mode 100644 index 0000000..240d7c1 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +I18n { + áâãäå: 15 +} diff --git a/tests/auto/declarative/qmllanguage/data/i18nScript.qml b/tests/auto/declarative/qmllanguage/data/i18nScript.qml new file mode 100644 index 0000000..6d07b03 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/i18nScript.qml @@ -0,0 +1,12 @@ +import Qt 4.6 + +Text { + Script { + function val() { + var áâãäå = 10 + return "Test áâãäå: " + áâãäå + } + + } + text: val() +} diff --git a/tests/auto/declarative/qmllanguage/data/i18nStrings.qml b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml new file mode 100644 index 0000000..062191f --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +Text { + text: "Test áâãäå (5 accented 'a' letters)" +} diff --git a/tests/auto/declarative/qmllanguage/data/i18nType.qml b/tests/auto/declarative/qmllanguage/data/i18nType.qml new file mode 100644 index 0000000..1a73096 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/i18nType.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +I18nÁâãäå { + text: "TEST" +} -- cgit v0.12 From 3a83d69ee744216bc72c1b67ad752a9640bb3605 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Mon, 12 Oct 2009 17:13:09 +1000 Subject: Allow Unicode identifiers. --- src/declarative/qml/parser/qmljslexer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/parser/qmljslexer.cpp b/src/declarative/qml/parser/qmljslexer.cpp index f71b92f..54f8d78 100644 --- a/src/declarative/qml/parser/qmljslexer.cpp +++ b/src/declarative/qml/parser/qmljslexer.cpp @@ -867,11 +867,16 @@ bool Lexer::isLineTerminator() const bool Lexer::isIdentLetter(ushort c) { - /* TODO: allow other legitimate unicode chars */ - return ((c >= 'a' && c <= 'z') + // ASCII-biased, since all reserved words are ASCII, aand hence the + // bulk of content to be parsed. + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '$' - || c == '_'); + || c == '_') + return true; + if (c < 128) + return false; + return QChar(c).isLetterOrNumber(); } bool Lexer::isDecimalDigit(ushort c) -- cgit v0.12 From 8d22b82d3883518b83bfb49dcc6e3506d0a8731e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 18:32:26 +1000 Subject: Doc --- doc/src/declarative/anatomy.qdoc | 74 +++++++++++++++++++++ doc/src/declarative/binding.qdoc | 33 ---------- doc/src/declarative/ecmascriptblocks.qdoc | 74 +++++++++++++++++++++ doc/src/declarative/network.qdoc | 53 +++++++++++++++ doc/src/declarative/propertybinding.qdoc | 103 ++++++++++++++++++++++++++++++ doc/src/declarative/qtdeclarative.qdoc | 5 +- doc/src/declarative/scope.qdoc | 49 ++++++++++++++ 7 files changed, 357 insertions(+), 34 deletions(-) create mode 100644 doc/src/declarative/anatomy.qdoc create mode 100644 doc/src/declarative/ecmascriptblocks.qdoc create mode 100644 doc/src/declarative/network.qdoc create mode 100644 doc/src/declarative/propertybinding.qdoc create mode 100644 doc/src/declarative/scope.qdoc diff --git a/doc/src/declarative/anatomy.qdoc b/doc/src/declarative/anatomy.qdoc new file mode 100644 index 0000000..f816464 --- /dev/null +++ b/doc/src/declarative/anatomy.qdoc @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page qmldocumentanatomy.html +\title Anatomy of a QML Document + +A QML document is a block of QML source code. QML documents generally correspond to files +stored on a disk or network resource, but can be constructed directly from text data. + +Syntactically a QML document is self contained; QML does \e not have a preprocessor that +modifies the document prior to presentation to the QML runtime. Type references made within +a QML document, including within a \l {ECMAScript Block} contained by the document, are +resolved based exclusively on the import statements present in the document. + +A simple QML document looks like this: + +\code +import Qt 4.6 + +Rectangle { + Component { + id: contactDelegate + Text { + text: modelData.firstName + " " + modelData.lastName + } + } + + ListView { + model: contactModel + delegate: contactDelegate + } +} +\endcode + +*/ diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc index 79ba6ac..94465a1 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/binding.qdoc @@ -40,39 +40,6 @@ ****************************************************************************/ /*! -\page binding.html -\title Property Binding - -Property binding is a declarative way of specifying the value of a property. Binding allows -a property's value to be expressed as an ECMAScript expression that defines the value relative -to other property values or data accessible in the application. The property value is -automatically kept up to date if the other properties or data values change. - -Bindings are created in QML when an expression is assigned to a property. For example, the following produces two rectangles of equal size (\c rect2 is bound to the size of \c rect1): -\code -Rectangle { id: rect1; width: 100; height: 100 } -Rectangle { id: rect2; width: rect1.width; height: rect1.height } -\endcode - -There is also a special \l Binding 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 Binding element as: - -\code -Binding { target: rect2; property: "width"; value: rect1.width } -Binding { 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. - -Data can be bound to C++ objects - see \l {QML/C++ Data Binding}. -*/ - -/*! \page qtbinding.html \target qtbinding \title QML/C++ Data Binding diff --git a/doc/src/declarative/ecmascriptblocks.qdoc b/doc/src/declarative/ecmascriptblocks.qdoc new file mode 100644 index 0000000..4dde19d --- /dev/null +++ b/doc/src/declarative/ecmascriptblocks.qdoc @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page qmlecmascript.html +\title ECMAScript Blocks + +QML encourages building UIs declaratively, using \l {Property Binding} and existing +\l {QML Elements}. When imperative code is required to implementing more advanced +behavior, the \l Script element can be used to add ECMAScript code directly to a +QML file, or to include an external ECMAScript file. + +The \l Script element is a QML language \e intrinsic. It can be used anywhere in a +QML file. \e except as the root element of a file or sub-component. The included +ECMAScript is evaluated in a scope chain. The \l {QML Scope} documentation covers +the specifics of scoping in QML. + +\section1 Inline ECMAScript + +\code +Rectangle { + Script { + function factorial(var a) { + a = Integer(a); + if (a <= 0) + return 1; + else + return a * factorial(a - 1); + } + } +} +\endcode + +\section1 Including a ECMAScript File + +*/ diff --git a/doc/src/declarative/network.qdoc b/doc/src/declarative/network.qdoc new file mode 100644 index 0000000..3d75706 --- /dev/null +++ b/doc/src/declarative/network.qdoc @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page qmlnetwork.html +\title Network Transparency + +\list +\o Documents and script blocks can be fetched transparently over the network (blocking) +\o Images, fonts can be fetched transparently over the network (non-blocking) +\o Configuring the network access manager +\o Relative URL resolution from ECMAScript/QML +\endlist + +*/ diff --git a/doc/src/declarative/propertybinding.qdoc b/doc/src/declarative/propertybinding.qdoc new file mode 100644 index 0000000..4cf08d8 --- /dev/null +++ b/doc/src/declarative/propertybinding.qdoc @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page propertybinding.html +\title Property Binding + +Property binding is a declarative way of specifying the value of a property. Binding allows +a property's value to be expressed as an ECMAScript expression that defines the value relative +to other property values or data accessible in the application. The property value is +automatically kept up to date if the other properties or data values change. + +Property bindings are created implicitly in QML whenever an property is assigned an ECMAScript +expression. The following QML uses two property bindings to connect the size of the rectangle +to that of \c otherItem. + +\code +Rectangle { + width: otherItem.width + height: otherItem.height +} +\endcode + +QML extends a standards compliant ECMAScript engine, so any valid ECMAScript expression can be +used as a property binding. Bindings can access object properties, make function calls and even +use builtin ECMAScript objects like \e {Date} and \e {Math}. Assigning a constant value to a +property can even be thought of as a binding - afterall, a constant is a valid ECMAScript +expression! Here are some examples of more complex bindings: + +\code +Rectangle { + Script { + function calculateMyWidth() { + return Math.max(otherItem.width, thirdItem.width); + } + } + + anchors.centerIn: parent + width: Math.min(otherItem.width, 10) + height: calculateMyWidth() + color: { if (width > 10) "blue"; else "red" } +} +\endcode + +Being ECMAScript expressions, bindings are evaluated in a scope chain. The \l {QML Scope} +documentation covers the specifics of scoping in QML. + +\list +\o When does a binding not get updated? +\o Scope +\o Assigning a constant/other binding clears existing binding +\o Loops +\o Using model data +\endlist + +\section1 Binding Element + +The implicit binding syntax shown previously is easy to use and works perfectly for most uses +of bindings. In some advanced cases, it is necessary to create bindings explicitly using the +\l Binding element. + +One such example is included in the \l {Passing Data Between C++ and QML} documentation. +\sa {QML/C++ Data Binding} +*/ + diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index d60f4ed..fa5c0e6 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -71,7 +71,10 @@ Core QML Features: \list + \o \l {Anatomy of a QML Document} \o \l {Property Binding} + \o \l {ECMAScript Blocks} + \o \l {Network Transparency} \o \l {qmlmodels}{Data Models} \o \l {anchor-layout}{Anchor-based Layout} \o \l {qmlanimation}{Animation} @@ -83,7 +86,7 @@ QML Reference: \list \o \l {QML Format Reference} - \o \l {elements}{QML Elements} + \o \l {QML Elements} \endlist C++ Reference: diff --git a/doc/src/declarative/scope.qdoc b/doc/src/declarative/scope.qdoc new file mode 100644 index 0000000..c35f3e3 --- /dev/null +++ b/doc/src/declarative/scope.qdoc @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page qmlscope.html +\title QML Scope + +QML is a \e {dynamically scoped} language. \l {Property Binding}s and \l {ECMAScript Blocks} +are executed + +*/ -- cgit v0.12 From 1813e81d0c04c447ee4d6d6fb286317b218c9696 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 19:16:27 +1000 Subject: Doc --- doc/src/declarative/qtdeclarative.qdoc | 104 ++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index fa5c0e6..549330b 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -40,58 +40,68 @@ ****************************************************************************/ /*! - \module QtDeclarative - \title QtDeclarative Module - \ingroup modules +\module QtDeclarative +\title QtDeclarative Module +\ingroup modules - \brief The Qt Declarative module provides a declarative framework for building - highly dynamic, custom UIs +\brief The Qt Declarative module provides a declarative framework for building +highly dynamic, custom UIs - Qt Declarative 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. +Qt Declarative aids programmers and designers in building the animation rich, +highly fluid user interfaces that are becoming common in portable consumer +electronics devices, such as mobile phones, media players, set-top boxes and +netbooks. The Qt Declarative module provides an engine for interpreting the +declarative QML language, and a rich set of \l {QML Elements} that can be used +from QML. - 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 - in an declarative format called QML, rather than specifying step-by-step \e how to - build it in a language like C++ or JavaScript. 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. +QML is an extension to \l {http://www.ecma-international.org/publications/standards/Ecma-262.htm} +{ECMAScript}, that provides a mechanism to declaratively build an object tree +of \l {QML Elements}. QML improves the integration between ECMAScript and Qt's +existing QObject based type system, adds support for automatic +\l {Property Binding}s and provides \l {Network Transparency} at the language +level. - Getting Started: - \list - \o \l {Introduction to the QML language} - \o \l {tutorial}{Tutorial: 'Hello World'} - \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} - \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} - \o \l {qmlexamples}{Examples} - \endlist +The \l {QML Elements} are a sophisticated set of graphical and behavioral building +blocks. \l {QML Elements} are combined together in QML files to build components +ranging in complexity from simple pushbuttons and sliders, to complete +internet-enabled applications like a \l {http://www.flickr.com}{flickr} photo browser. - Core QML Features: - \list - \o \l {Anatomy of a QML Document} - \o \l {Property Binding} - \o \l {ECMAScript Blocks} - \o \l {Network Transparency} - \o \l {qmlmodels}{Data Models} - \o \l {anchor-layout}{Anchor-based Layout} - \o \l {qmlanimation}{Animation} - \o \l {qmlmodules}{Modules} - \o \l {qmlfocus}{Keyboard Focus} - \o \l {Extending types from QML} - \endlist +Qt Declarative builds on \l {QML for Qt programmers}{Qt's existing strengths}. +QML can be be used to incrementally extend an existing application or to build +completely new applications. QML is fully \l {Extending QML}{extensible from C++}. - QML Reference: - \list - \o \l {QML Format Reference} - \o \l {QML Elements} - \endlist +\section1 Getting Started: +\list +\o \l {Introduction to the QML language} +\o \l {tutorial}{Tutorial: 'Hello World'} +\o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} +\o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} +\o \l {qmlexamples}{Examples} +\endlist - C++ Reference: - \list - \o \l {Extending QML} - \o \l {qtbinding}{QML/C++ Data Binding} - \endlist +\section1 Core QML Features: +\list +\o \l {Anatomy of a QML Document} +\o \l {Property Binding} +\o \l {ECMAScript Blocks} +\o \l {Network Transparency} +\o \l {qmlmodels}{Data Models} +\o \l {anchor-layout}{Anchor-based Layout} +\o \l {qmlanimation}{Animation} +\o \l {qmlmodules}{Modules} +\o \l {qmlfocus}{Keyboard Focus} +\o \l {Extending types from QML} +\endlist + +\section1 QML Reference: +\list +\o \l {QML Format Reference} +\o \l {QML Elements} +\endlist + +\section1 C++ Reference: +\list +\o \l {Extending QML} +\o \l {qtbinding}{QML/C++ Data Binding} +\endlist */ -- cgit v0.12 From 65dfb60a64d31baa555e6c52ccf3aad4309a9db3 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 12 Oct 2009 19:21:24 +1000 Subject: Doc --- doc/src/declarative/examples.qdoc | 1 - doc/src/declarative/qtdeclarative.qdoc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc index 5408098..7a03685 100644 --- a/doc/src/declarative/examples.qdoc +++ b/doc/src/declarative/examples.qdoc @@ -41,7 +41,6 @@ /*! \page qmlexamples.html -\target qmlexamples \title QML Examples A \l {qmlviewer}{viewer} application is included that allows you to quickly explore many of the diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index 549330b..56f3252 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -76,7 +76,7 @@ completely new applications. QML is fully \l {Extending QML}{extensible from C+ \o \l {tutorial}{Tutorial: 'Hello World'} \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} -\o \l {qmlexamples}{Examples} +\o \l {QML Examples} \endlist \section1 Core QML Features: -- cgit v0.12 From 231604bc063c002240479b69baa8110c2c83e9e1 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 13 Oct 2009 08:42:30 +1000 Subject: Behavior fix plus basic autotests. --- src/declarative/qml/qmlmetaproperty.cpp | 1 - src/declarative/util/qmlanimation.cpp | 8 ++ tests/auto/declarative/behaviors/behaviors.pro | 5 + tests/auto/declarative/behaviors/data/binding.qml | 26 ++++ tests/auto/declarative/behaviors/data/color.qml | 24 ++++ .../auto/declarative/behaviors/data/cpptrigger.qml | 11 ++ .../declarative/behaviors/data/groupProperty.qml | 23 +++ .../declarative/behaviors/data/groupProperty2.qml | 23 +++ tests/auto/declarative/behaviors/data/loop.qml | 19 +++ .../declarative/behaviors/data/scripttrigger.qml | 16 +++ tests/auto/declarative/behaviors/data/simple.qml | 23 +++ tests/auto/declarative/behaviors/tst_behaviors.cpp | 154 +++++++++++++++++++++ 12 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/behaviors/behaviors.pro create mode 100644 tests/auto/declarative/behaviors/data/binding.qml create mode 100644 tests/auto/declarative/behaviors/data/color.qml create mode 100644 tests/auto/declarative/behaviors/data/cpptrigger.qml create mode 100644 tests/auto/declarative/behaviors/data/groupProperty.qml create mode 100644 tests/auto/declarative/behaviors/data/groupProperty2.qml create mode 100644 tests/auto/declarative/behaviors/data/loop.qml create mode 100644 tests/auto/declarative/behaviors/data/scripttrigger.qml create mode 100644 tests/auto/declarative/behaviors/data/simple.qml create mode 100644 tests/auto/declarative/behaviors/tst_behaviors.cpp diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 8643301..59699ef 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -737,7 +737,6 @@ bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int id return false; QVariant v = value; - uint t = QVariant::Invalid; if (prop.isEnumType()) { QMetaEnum menum = prop.enumerator(); if (v.type() == QVariant::String diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 247e64c..9c5708e 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -1767,8 +1767,13 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, int prevInterpolatorType; //for generic QVariantAnimation::Interpolator interpolator; bool reverse; + bool *wasDeleted; + PropertyUpdater() : wasDeleted(0) {} + ~PropertyUpdater() { if (wasDeleted) *wasDeleted = true; } void setValue(qreal v) { + bool deleted = false; + wasDeleted = &deleted; if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1 v = 1 - v; QmlTimeLineValue::setValue(v); @@ -1793,7 +1798,10 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, if (interpolator) action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } + if (deleted) + return; } + wasDeleted = 0; } }; diff --git a/tests/auto/declarative/behaviors/behaviors.pro b/tests/auto/declarative/behaviors/behaviors.pro new file mode 100644 index 0000000..c96d2c0 --- /dev/null +++ b/tests/auto/declarative/behaviors/behaviors.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +SOURCES += tst_behaviors.cpp + +DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/declarative/behaviors/data/binding.qml b/tests/auto/declarative/behaviors/data/binding.qml new file mode 100644 index 0000000..e0c3321 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/binding.qml @@ -0,0 +1,26 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + property real basex : 0 + property real movedx: 200 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + x: basex + x: Behavior { NumberAnimation { duration: 200; } } + } + MouseRegion { + id: clicker + anchors.fill: parent + } + states: State { + name: "moved" + when: clicker.pressed + PropertyChanges { + target: rect + x: movedx + } + } +} diff --git a/tests/auto/declarative/behaviors/data/color.qml b/tests/auto/declarative/behaviors/data/color.qml new file mode 100644 index 0000000..6598703 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/color.qml @@ -0,0 +1,24 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; + color: "green" + color: Behavior { ColorAnimation { duration: 200; } } + } + MouseRegion { + id: clicker + anchors.fill: parent + } + states: State { + name: "red" + when: clicker.pressed + PropertyChanges { + target: rect + color: "red" + } + } +} diff --git a/tests/auto/declarative/behaviors/data/cpptrigger.qml b/tests/auto/declarative/behaviors/data/cpptrigger.qml new file mode 100644 index 0000000..ba507c4 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/cpptrigger.qml @@ -0,0 +1,11 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + x: Behavior { NumberAnimation { duration: 200; } } + } +} diff --git a/tests/auto/declarative/behaviors/data/groupProperty.qml b/tests/auto/declarative/behaviors/data/groupProperty.qml new file mode 100644 index 0000000..4f127c1 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/groupProperty.qml @@ -0,0 +1,23 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + pos: Behavior { PropertyAnimation { duration: 200; } } + } + MouseRegion { + id: clicker + anchors.fill: parent + } + states: State { + name: "moved" + when: clicker.pressed + PropertyChanges { + target: rect + pos: Qt.point(200,0); + } + } +} diff --git a/tests/auto/declarative/behaviors/data/groupProperty2.qml b/tests/auto/declarative/behaviors/data/groupProperty2.qml new file mode 100644 index 0000000..19d70b6 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/groupProperty2.qml @@ -0,0 +1,23 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + pos.x: Behavior { NumberAnimation { duration: 200; } } + } + MouseRegion { + id: clicker + anchors.fill: parent + } + states: State { + name: "moved" + when: clicker.pressed + PropertyChanges { + target: rect + pos.x: 200; + } + } +} diff --git a/tests/auto/declarative/behaviors/data/loop.qml b/tests/auto/declarative/behaviors/data/loop.qml new file mode 100644 index 0000000..5f2c057 --- /dev/null +++ b/tests/auto/declarative/behaviors/data/loop.qml @@ -0,0 +1,19 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + x: Behavior { NumberAnimation { duration: 200; } } + onXChanged: x = 100; + } + states: State { + name: "moved" + PropertyChanges { + target: rect + x: 200 + } + } +} diff --git a/tests/auto/declarative/behaviors/data/scripttrigger.qml b/tests/auto/declarative/behaviors/data/scripttrigger.qml new file mode 100644 index 0000000..4383a0b --- /dev/null +++ b/tests/auto/declarative/behaviors/data/scripttrigger.qml @@ -0,0 +1,16 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + + onColorChanged: { + rect.x = 200 + } + + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + x: Behavior { NumberAnimation { duration: 200; } } + } +} diff --git a/tests/auto/declarative/behaviors/data/simple.qml b/tests/auto/declarative/behaviors/data/simple.qml new file mode 100644 index 0000000..a715f7b --- /dev/null +++ b/tests/auto/declarative/behaviors/data/simple.qml @@ -0,0 +1,23 @@ +import Qt 4.6 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRect" + width: 100; height: 100; color: "green" + x: Behavior { NumberAnimation { duration: 200; } } + } + MouseRegion { + id: clicker + anchors.fill: parent + } + states: State { + name: "moved" + when: clicker.pressed + PropertyChanges { + target: rect + x: 200 + } + } +} diff --git a/tests/auto/declarative/behaviors/tst_behaviors.cpp b/tests/auto/declarative/behaviors/tst_behaviors.cpp new file mode 100644 index 0000000..7bfadf6 --- /dev/null +++ b/tests/auto/declarative/behaviors/tst_behaviors.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include + +class tst_behaviors : public QObject +{ + Q_OBJECT +public: + tst_behaviors() {} + +private slots: + void simpleBehavior(); + void scriptTriggered(); + void cppTriggered(); + void loop(); + void colorBehavior(); + void replaceBinding(); + //void transitionOverrides(); + void group(); +}; + +void tst_behaviors::simpleBehavior() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/simple.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setState("moved"); + QTest::qWait(100); + qreal x = qobject_cast(rect->findChild("MyRect"))->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered +} + +void tst_behaviors::scriptTriggered() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/scripttrigger.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setColor(QColor("red")); + QTest::qWait(100); + qreal x = qobject_cast(rect->findChild("MyRect"))->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered +} + +void tst_behaviors::cppTriggered() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/cpptrigger.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + QFxRect *innerRect = qobject_cast(rect->findChild("MyRect")); + QVERIFY(innerRect); + + innerRect->setProperty("x", 200); + QTest::qWait(100); + qreal x = innerRect->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered +} + +void tst_behaviors::loop() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/loop.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + //don't crash + rect->setState("moved"); +} + +void tst_behaviors::colorBehavior() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/color.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setState("red"); + QTest::qWait(100); + QColor color = qobject_cast(rect->findChild("MyRect"))->color(); + QVERIFY(color != QColor("red") && color != QColor("green")); //i.e. the behavior has been triggered +} + +void tst_behaviors::replaceBinding() +{ + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/binding.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setState("moved"); + QTest::qWait(100); + QFxRect *innerRect = qobject_cast(rect->findChild("MyRect")); + QVERIFY(innerRect); + qreal x = innerRect->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered + QTest::qWait(300); + QCOMPARE(innerRect->x(), (qreal)200); + rect->setProperty("basex", 10); + QCOMPARE(innerRect->x(), (qreal)200); + rect->setProperty("movedx", 210); + QTest::qWait(300); + QCOMPARE(innerRect->x(), (qreal)210); + + rect->setState(""); + QTest::qWait(100); + x = innerRect->x(); + QVERIFY(x > 10 && x < 210); //i.e. the behavior has been triggered + QTest::qWait(300); + QCOMPARE(innerRect->x(), (qreal)10); + rect->setProperty("movedx", 200); + QCOMPARE(innerRect->x(), (qreal)10); + rect->setProperty("basex", 20); + QTest::qWait(300); + QCOMPARE(innerRect->x(), (qreal)20); +} + +void tst_behaviors::group() +{ + { + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/groupProperty.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setState("moved"); + QTest::qWait(100); + qreal x = qobject_cast(rect->findChild("MyRect"))->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered + } + + { + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/groupProperty2.qml")); + QFxRect *rect = qobject_cast(c.create()); + QVERIFY(rect); + + rect->setState("moved"); + QTest::qWait(100); + qreal x = qobject_cast(rect->findChild("MyRect"))->x(); + QVERIFY(x > 0 && x < 200); //i.e. the behavior has been triggered + } +} + +QTEST_MAIN(tst_behaviors) + +#include "tst_behaviors.moc" -- cgit v0.12 From f88fe352c148b0aea633fca2b81d6a2c7782bb87 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 13 Oct 2009 09:45:42 +1000 Subject: Fix some of the ListView remove tests. The remainder are bugs. --- tests/auto/declarative/listview/tst_listview.cpp | 34 +++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tests/auto/declarative/listview/tst_listview.cpp b/tests/auto/declarative/listview/tst_listview.cpp index 2a5fa1c..1875836 100644 --- a/tests/auto/declarative/listview/tst_listview.cpp +++ b/tests/auto/declarative/listview/tst_listview.cpp @@ -34,6 +34,8 @@ private: QmlView *createView(const QString &filename); template T *findItem(QFxItem *parent, const QString &id, int index=-1); + template + QList findItems(QFxItem *parent, const QString &objectName); }; class TestModel : public QListModelInterface @@ -336,7 +338,8 @@ void tst_QFxListView::removed() QCOMPARE(number->text(), model.number(1)); // Confirm items positioned correctly - for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { + int itemCount = findItems(viewport, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { QFxItem *item = findItem(viewport, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QVERIFY(item); @@ -357,7 +360,8 @@ void tst_QFxListView::removed() QCOMPARE(number->text(), model.number(0)); // Confirm items positioned correctly - for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { + itemCount = findItems(viewport, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { QFxItem *item = findItem(viewport, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QVERIFY(item); @@ -370,7 +374,8 @@ void tst_QFxListView::removed() QTest::qWait(1000); // Confirm items positioned correctly - for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { + itemCount = findItems(viewport, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { QFxItem *item = findItem(viewport, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QVERIFY(item); @@ -398,7 +403,8 @@ void tst_QFxListView::removed() QTest::qWait(1000); // Confirm items positioned correctly - for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { + itemCount = findItems(viewport, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { QFxItem *item = findItem(viewport, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QVERIFY(item); @@ -493,6 +499,26 @@ T *tst_QFxListView::findItem(QFxItem *parent, const QString &objectName, int ind return 0; } +template +QList tst_QFxListView::findItems(QFxItem *parent, const QString &objectName) +{ + QList items; + const QMetaObject &mo = T::staticMetaObject; + //qDebug() << parent->QGraphicsObject::children().count() << "children"; + for (int i = 0; i < parent->QGraphicsObject::children().count(); ++i) { + QFxItem *item = qobject_cast(parent->QGraphicsObject::children().at(i)); + if(!item) + continue; + //qDebug() << "try" << item; + if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) + items.append(static_cast(item)); + items += findItems(item, objectName); + } + + return items; +} + + QTEST_MAIN(tst_QFxListView) #include "tst_listview.moc" -- cgit v0.12 From f0e328e0a59cdd9b9cfcea46cef07bf2ff8eebad Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 13 Oct 2009 09:47:20 +1000 Subject: Add basic QML docs for the effects. --- doc/src/declarative/elements.qdoc | 7 ++ src/declarative/fx/fx.pri | 1 + src/declarative/fx/qfxeffects.cpp | 238 ++++++++++++++++++++++++++++++++++++++ src/declarative/fx/qfxitem.cpp | 24 ---- 4 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 src/declarative/fx/qfxeffects.cpp diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index 98c4ee1..4fa4ec5 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -185,6 +185,13 @@ The following table lists the QML elements provided by the Qt Declarative module \o \list +\o \l Blur +\o \l Colorize +\o \l Grayscale +\o \l Pixelize +\o \l DropShadow +\o \l Opacity +\o \l Bloom \o \l Particles \list \o \l ParticleMotionLinear diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri index cfe78e1..fc4e640 100644 --- a/src/declarative/fx/fx.pri +++ b/src/declarative/fx/fx.pri @@ -44,6 +44,7 @@ HEADERS += \ fx/qfxlistview.h \ fx/qfxgraphicsobjectcontainer.h \ fx/qfxlayoutitem.h \ + fx/qfxeffects.cpp SOURCES += \ fx/qfxanchors.cpp \ diff --git a/src/declarative/fx/qfxeffects.cpp b/src/declarative/fx/qfxeffects.cpp new file mode 100644 index 0000000..ebdd880 --- /dev/null +++ b/src/declarative/fx/qfxeffects.cpp @@ -0,0 +1,238 @@ +#include +#include +#include + +QML_DECLARE_TYPE(QGraphicsEffect) +QML_DEFINE_NOCREATE_TYPE(QGraphicsEffect) + +QML_DECLARE_TYPE(QGraphicsBlurEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Blur,QGraphicsBlurEffect) + +/*! + \qmlclass Blur + \brief The Blur object provides a blur effect. + + A blur effect blurs the source item. This effect is useful for reducing details, + such as when the source loses focus and you want to draw attention to other + elements. The level of detail can be modified using the blurRadius property. + Use blurHint to choose the quality or performance blur hints. + + By default, the blur radius is 5 pixels. + + \img graphicseffect-blur.png +*/ + +/*! + \qmlproperty real Blur::blurRadius + + blurRadius controls how blurry an item will appear. + Using a smaller radius results in a sharper appearance, whereas a bigger + radius results in a more blurred appearance. + + By default, the blur radius is 5 pixels. +*/ +/*! + \qmlproperty enumeration Blur::blurHint + + Use the Qt.PerformanceHint hint to say that you want a faster blur, + and the Qt.QualityHint hint to say that you prefer a higher quality blur. + + When animating the blur radius it's recommended to use Qt.PerformanceHint. + + By default, the blur hint is Qt.PerformanceHint. +*/ + +QML_DECLARE_TYPE(QGraphicsGrayscaleEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Grayscale,QGraphicsGrayscaleEffect) + +/*! + \qmlclass Grayscale + \brief The Grayscale object provides a grayscale effect. + + A grayscale effect renders the source item in shades of gray. + + \img graphicseffect-grayscale.png +*/ + +/*! + \qmlproperty real Grayscale::strength + + To what extent the source item is "grayed". A strength of 0.0 is equal to no effect, + while 1.0 means full grayscale. By default, the strength is 1.0. +*/ + +QML_DECLARE_TYPE(QGraphicsColorizeEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Colorize,QGraphicsColorizeEffect) + +/*! + \qmlclass Colorize + \brief The Colorize object provides a colorize effect. + + A colorize effect renders the source item with a tint of its color. + + By default, the color is light blue. + + \img graphicseffect-colorize.png +*/ + +/*! + \qmlproperty color Colorize::color + The color of the effect. + + By default, the color is light blue. +*/ + +/*! + \qmlproperty real Colorize::strength + + To what extent the source item is "colored". A strength of 0.0 is equal to no effect, + while 1.0 means full colorization. By default, the strength is 1.0. +*/ + +QML_DECLARE_TYPE(QGraphicsPixelizeEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Pixelize,QGraphicsPixelizeEffect) + +/*! + \qmlclass Pixelize + \brief The Pixelize object provides a pixelize effect. + + A pixelize effect renders the source item in lower resolution. The resolution + can be modified using the pixelSize property. + + By default, the pixel size is 3. + + \img graphicseffect-pixelize.png +*/ + +/*! + \qmlproperty int Pixelize::pixelSize + The size of a pixel in the effect. + + Setting the pixel size to 2 means two pixels in the source item will be used to + represent one pixel in the output. Using a bigger size results in lower resolution. + + By default, the pixel size is 3. +*/ + + +QML_DECLARE_TYPE(QGraphicsDropShadowEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,DropShadow,QGraphicsDropShadowEffect) + +/*! + \qmlclass DropShadow + \brief The DropShadow object provides a drop shadow effect. + + A drop shadow effect renders the source item with a drop shadow. The color of + the drop shadow can be modified using the color property. The drop + shadow offset can be modified using the xOffset and yOffset properties and the blur + radius of the drop shadow can be changed with the blurRadius property. + + By default, the drop shadow is a semi-transparent dark gray shadow, + blurred with a radius of 1 at an offset of 8 pixels towards the lower right. + + \img graphicseffect-drop-shadow.png +*/ + +/*! + \qmlproperty real DropShadow::xOffset + \qmlproperty real DropShadow::yOffset + The shadow offset in pixels. + + By default, xOffset and yOffset are 8 pixels. +*/ + +/*! + \qmlproperty real DropShadow::blurRadius + The blur radius in pixels of the drop shadow. + + Using a smaller radius results in a sharper shadow, whereas using a bigger + radius results in a more blurred shadow. + + By default, the blur radius is 1 pixel. +*/ + +/*! + \qmlproperty color DropShadow::color + The color of the drop shadow. + + By default, the drop color is a semi-transparent dark gray. +*/ + +QML_DECLARE_TYPE(QGraphicsOpacityEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Opacity,QGraphicsOpacityEffect) + +/*! + \qmlclass Opacity + \brief The Opacity object provides an opacity effect. + + An opacity effect renders the source with an opacity. This effect is useful + for making the source semi-transparent, similar to a fade-in/fade-out + sequence. The opacity can be modified using the opacity property. + + By default, the opacity is 0.7. + + \img graphicseffect-opacity.png +*/ + +/*! + \qmlproperty real Opacity::opacity + This property specifies how opaque an item should appear. + + The value should be in the range of 0.0 to 1.0, where 0.0 is + fully transparent and 1.0 is fully opaque. + + By default, the opacity is 0.7. +*/ + +QML_DECLARE_TYPE(QGraphicsBloomEffect) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Bloom,QGraphicsBloomEffect) + +/*! + \qmlclass Bloom + \brief The Bloom object provides a bloom/glow effect. + + A bloom/glow effect adds fringes of light around bright areas in the source item. + + \img graphicseffect-bloom.png +*/ + +/*! + \qmlproperty real Bloom::blurRadius + The blur radius in pixels of the effect. + + Using a smaller radius results in a sharper appearance, whereas a bigger + radius results in a more blurred appearance. + + By default, the blur radius is 5 pixels. +*/ + +/*! + \qmlproperty enumeration Bloom::blurHint + + Use the Qt.PerformanceHint hint to say that you want a faster blur, + and the Qt.QualityHint hint to say that you prefer a higher quality blur. + + When animating the blur radius it's recommended to use Qt.PerformanceHint. + + By default, the blur hint is Qt.PerformanceHint. +*/ + +/*! + \qmlproperty int Bloom::brightness + This property specifies how bright the glow should appear. + + The value should be in the range of 0 to 255, where 0 is dark + and 255 is bright. + + By default, the brightness is 70. +*/ + +/*! + \qmlproperty real Bloom::strength + The strength of the glow. + + A strength of 0.0 is equal to no effect, while 1.0 means maximum glow. + + By default, the strength is 0.7. +*/ + diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index a155d5a..8ba0759 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -76,30 +76,6 @@ QML_DEFINE_NOCREATE_TYPE(QGraphicsTransform); QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Scale,QGraphicsScale) QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Rotation,QGraphicsRotation) -QML_DECLARE_TYPE(QGraphicsEffect) -QML_DEFINE_NOCREATE_TYPE(QGraphicsEffect) - -QML_DECLARE_TYPE(QGraphicsBlurEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Blur,QGraphicsBlurEffect) - -QML_DECLARE_TYPE(QGraphicsGrayscaleEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Grayscale,QGraphicsGrayscaleEffect) - -QML_DECLARE_TYPE(QGraphicsColorizeEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Colorize,QGraphicsColorizeEffect) - -QML_DECLARE_TYPE(QGraphicsPixelizeEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Pixelize,QGraphicsPixelizeEffect) - -QML_DECLARE_TYPE(QGraphicsDropShadowEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,DropShadow,QGraphicsDropShadowEffect) - -QML_DECLARE_TYPE(QGraphicsOpacityEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Opacity,QGraphicsOpacityEffect) - -QML_DECLARE_TYPE(QGraphicsBloomEffect) -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Bloom,QGraphicsBloomEffect) - /*! \qmlclass Transform \brief A transformation. -- cgit v0.12 From d71db342a34690438878684f054dca820f77b1b9 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 13 Oct 2009 09:48:25 +1000 Subject: Fix UTF8 vs. Latin1 conversion I18n tests --- src/declarative/qml/qmlengine.cpp | 2 +- tests/auto/declarative/qmllanguage/data/I18n.qml | 6 ++--- ...8n\303\201\303\242\303\243\303\244\303\245.qml" | 5 +++-- .../qmllanguage/data/i18nDeclaredPropertyNames.qml | 6 ++--- .../qmllanguage/data/i18nDeclaredPropertyUse.qml | 2 -- .../declarative/qmllanguage/data/i18nScript.qml | 8 +++---- .../declarative/qmllanguage/data/i18nStrings.qml | 6 ++--- .../auto/declarative/qmllanguage/data/i18nType.qml | 6 +---- .../declarative/qmllanguage/tst_qmllanguage.cpp | 26 ++++++++++++++++++++++ 9 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 245ddc0..ef0f975 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -1106,7 +1106,7 @@ public: } } if (url_return) { - *url_return = base.resolved(QUrl(QLatin1String(type + ".qml"))); + *url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml"))); return true; } else { return false; diff --git a/tests/auto/declarative/qmllanguage/data/I18n.qml b/tests/auto/declarative/qmllanguage/data/I18n.qml index dbbd4bd..558c836 100644 --- a/tests/auto/declarative/qmllanguage/data/I18n.qml +++ b/tests/auto/declarative/qmllanguage/data/I18n.qml @@ -1,6 +1,6 @@ -import Qt 4.6 +import Test 1.0 -Text { +MyTypeObject { property int áâãäå: 10 - text: "Test áâãäå: " + áâãäå + stringProperty: "Test áâãäå: " + áâãäå } diff --git "a/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" "b/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" index 6a841d1..42dbc69 100644 --- "a/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" +++ "b/tests/auto/declarative/qmllanguage/data/I18n\303\201\303\242\303\243\303\244\303\245.qml" @@ -1,4 +1,5 @@ -import Qt 4.6 +import Test 1.0 -Text { +MyTypeObject { + stringProperty: "Test áâãäå: 30" } diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml index dbbd4bd..558c836 100644 --- a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml +++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyNames.qml @@ -1,6 +1,6 @@ -import Qt 4.6 +import Test 1.0 -Text { +MyTypeObject { property int áâãäå: 10 - text: "Test áâãäå: " + áâãäå + stringProperty: "Test áâãäå: " + áâãäå } diff --git a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml index 240d7c1..74918e2 100644 --- a/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml +++ b/tests/auto/declarative/qmllanguage/data/i18nDeclaredPropertyUse.qml @@ -1,5 +1,3 @@ -import Qt 4.6 - I18n { áâãäå: 15 } diff --git a/tests/auto/declarative/qmllanguage/data/i18nScript.qml b/tests/auto/declarative/qmllanguage/data/i18nScript.qml index 6d07b03..942ed90 100644 --- a/tests/auto/declarative/qmllanguage/data/i18nScript.qml +++ b/tests/auto/declarative/qmllanguage/data/i18nScript.qml @@ -1,12 +1,12 @@ -import Qt 4.6 +import Test 1.0 -Text { +MyTypeObject { Script { function val() { - var áâãäå = 10 + var áâãäå = 20 return "Test áâãäå: " + áâãäå } } - text: val() + stringProperty: val() } diff --git a/tests/auto/declarative/qmllanguage/data/i18nStrings.qml b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml index 062191f..764c926 100644 --- a/tests/auto/declarative/qmllanguage/data/i18nStrings.qml +++ b/tests/auto/declarative/qmllanguage/data/i18nStrings.qml @@ -1,5 +1,5 @@ -import Qt 4.6 +import Test 1.0 -Text { - text: "Test áâãäå (5 accented 'a' letters)" +MyTypeObject { + stringProperty: "Test áâãäå (5 accented 'a' letters)" } diff --git a/tests/auto/declarative/qmllanguage/data/i18nType.qml b/tests/auto/declarative/qmllanguage/data/i18nType.qml index 1a73096..11ef895 100644 --- a/tests/auto/declarative/qmllanguage/data/i18nType.qml +++ b/tests/auto/declarative/qmllanguage/data/i18nType.qml @@ -1,5 +1 @@ -import Qt 4.6 - -I18nÁâãäå { - text: "TEST" -} +I18nÁâãäå { } diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index a991144..cf42792 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -58,6 +58,8 @@ private slots: void cppnamespace(); void aliasProperties(); void componentCompositeType(); + void i18n(); + void i18n_data(); void importsBuiltin_data(); void importsBuiltin(); @@ -679,6 +681,30 @@ public: TestType2(QObject *p=0) : QObject(p) {} }; +void tst_qmllanguage::i18n_data() +{ + QTest::addColumn("file"); + QTest::addColumn("stringProperty"); + QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test áâãäå (5 accented 'a' letters)"); + QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test áâãäå: 10"); + QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test áâãäå: 15"); + QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test áâãäå: 20"); + QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test áâãäå: 30"); +} + +void tst_qmllanguage::i18n() +{ + QFETCH(QString, file); + QFETCH(QString, stringProperty); + QmlComponent component(&engine, TEST_FILE(file)); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->stringProperty(), stringProperty); + + delete object; +} + // Check that first child of qml is of given type. Empty type insists on error. void tst_qmllanguage::testType(const QString& qml, const QString& type) { -- cgit v0.12 From a35d64024103df9150bbbc21298bee6e0ab8cd93 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 13 Oct 2009 09:55:45 +1000 Subject: Readd basic Behavior documentation. --- src/declarative/extra/qmlbehavior.cpp | 36 +++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/declarative/extra/qmlbehavior.cpp b/src/declarative/extra/qmlbehavior.cpp index e30bd39..1cf0d38 100644 --- a/src/declarative/extra/qmlbehavior.cpp +++ b/src/declarative/extra/qmlbehavior.cpp @@ -62,11 +62,43 @@ public: QmlAbstractAnimation *animation; }; +/*! + \qmlclass Behavior QmlBehavior + \brief The Behavior element allows you to specify a default animation for a property change. + + In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property: + \code + Rectangle { + width: 20; height: 20 + color: "#00ff00" + y: 200 //initial value + y: Behavior { + NumberAnimation { + easing: "easeOutBounce(amplitude:100)" + duration: 200 + } + } + } + \endcode +*/ + + QmlBehavior::QmlBehavior(QObject *parent) : QObject(*(new QmlBehaviorPrivate), parent) { } +QmlBehavior::~QmlBehavior() +{ +} + +/*! + \qmlproperty Animation Behavior::animation + \default + + The animation to use when the behavior is triggered. +*/ + QmlAbstractAnimation *QmlBehavior::animation() { Q_D(QmlBehavior); @@ -86,10 +118,6 @@ void QmlBehavior::setAnimation(QmlAbstractAnimation *animation) d->animation->setTarget(d->property); } -QmlBehavior::~QmlBehavior() -{ -} - void QmlBehavior::write(const QVariant &value) { Q_D(QmlBehavior); -- cgit v0.12 From 3b0c979986a692c58b6c72a284070e700c09b9c4 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 13 Oct 2009 11:14:36 +1000 Subject: Add autotest for overriding a signal handler in a state change. --- .../declarative/states/data/ExtendedRectangle.qml | 19 ++++++++ .../declarative/states/data/signalOverride.qml | 18 ++++++++ .../declarative/states/data/signalOverride2.qml | 9 ++++ tests/auto/declarative/states/tst_states.cpp | 51 ++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 tests/auto/declarative/states/data/ExtendedRectangle.qml create mode 100644 tests/auto/declarative/states/data/signalOverride.qml create mode 100644 tests/auto/declarative/states/data/signalOverride2.qml diff --git a/tests/auto/declarative/states/data/ExtendedRectangle.qml b/tests/auto/declarative/states/data/ExtendedRectangle.qml new file mode 100644 index 0000000..8d64663 --- /dev/null +++ b/tests/auto/declarative/states/data/ExtendedRectangle.qml @@ -0,0 +1,19 @@ +import Qt 4.6 +Rectangle { + id: extendedRect + objectName: "extendedRect" + property color extendedColor: "orange" + + width: 100; height: 100 + color: "red" + states: State { + name: "green" + PropertyChanges { + target: rect + onDidSomething: { + extendedRect.color = "green" + extendedColor = "green" + } + } + } +} diff --git a/tests/auto/declarative/states/data/signalOverride.qml b/tests/auto/declarative/states/data/signalOverride.qml new file mode 100644 index 0000000..5ba1566 --- /dev/null +++ b/tests/auto/declarative/states/data/signalOverride.qml @@ -0,0 +1,18 @@ +import Qt 4.6 +import Qt.test 1.0 + +MyRectangle { + id: rect + + onDidSomething: color = "blue" + + width: 100; height: 100 + color: "red" + states: State { + name: "green" + PropertyChanges { + target: rect + onDidSomething: color = "green" + } + } +} diff --git a/tests/auto/declarative/states/data/signalOverride2.qml b/tests/auto/declarative/states/data/signalOverride2.qml new file mode 100644 index 0000000..527e165 --- /dev/null +++ b/tests/auto/declarative/states/data/signalOverride2.qml @@ -0,0 +1,9 @@ +import Qt 4.6 +import Qt.test 1.0 + +MyRectangle { + id: rect + onDidSomething: color = "blue" + width: 100; height: 100 + ExtendedRectangle {} +} diff --git a/tests/auto/declarative/states/tst_states.cpp b/tests/auto/declarative/states/tst_states.cpp index 3a61bd6..b2532a2 100644 --- a/tests/auto/declarative/states/tst_states.cpp +++ b/tests/auto/declarative/states/tst_states.cpp @@ -13,6 +13,7 @@ private slots: void basicChanges(); void basicExtension(); void basicBinding(); + void signalOverride(); }; void tst_states::basicChanges() @@ -262,6 +263,56 @@ void tst_states::basicBinding() } } +class MyRect : public QFxRect +{ + Q_OBJECT +public: + MyRect() {} + void doSomething() { emit didSomething(); } +Q_SIGNALS: + void didSomething(); +}; + +QML_DECLARE_TYPE(MyRect) +QML_DEFINE_TYPE(Qt.test, 1, 0, 0, MyRectangle,MyRect); + +void tst_states::signalOverride() +{ + QmlEngine engine; + + { + QmlComponent rectComponent(&engine, SRCDIR "/data/signalOverride.qml"); + MyRect *rect = qobject_cast(rectComponent.create()); + QVERIFY(rect != 0); + + QCOMPARE(rect->color(),QColor("red")); + rect->doSomething(); + QCOMPARE(rect->color(),QColor("blue")); + + rect->setState("green"); + rect->doSomething(); + QCOMPARE(rect->color(),QColor("green")); + } + + { + QmlComponent rectComponent(&engine, SRCDIR "/data/signalOverride2.qml"); + MyRect *rect = qobject_cast(rectComponent.create()); + QVERIFY(rect != 0); + + QCOMPARE(rect->color(),QColor("white")); + rect->doSomething(); + QCOMPARE(rect->color(),QColor("blue")); + + QFxRect *innerRect = qobject_cast(rect->findChild("extendedRect")); + + innerRect->setState("green"); + rect->doSomething(); + QCOMPARE(rect->color(),QColor("blue")); + QCOMPARE(innerRect->color(),QColor("green")); + QCOMPARE(innerRect->property("extendedColor").value(),QColor("green")); + } +} + QTEST_MAIN(tst_states) #include "tst_states.moc" -- cgit v0.12 From d39b7ce65f051da342dcc931e303a73339288c5e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 13 Oct 2009 11:27:26 +1000 Subject: Make sure effects are still included. --- src/declarative/fx/qfxitem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 8ba0759..6324724 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -76,6 +76,8 @@ QML_DEFINE_NOCREATE_TYPE(QGraphicsTransform); QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Scale,QGraphicsScale) QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Rotation,QGraphicsRotation) +#include "qfxeffects.cpp" + /*! \qmlclass Transform \brief A transformation. -- cgit v0.12 From 5e31c0cae45bae6f66decfb37825ed5d445e49e4 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 13 Oct 2009 12:36:05 +1000 Subject: More i18n --- src/declarative/extra/qmlbehavior.cpp | 2 +- src/declarative/extra/qmlxmllistmodel.cpp | 4 +- src/declarative/fx/qfxanchors.cpp | 30 ++-- src/declarative/fx/qfxflipable.cpp | 4 +- src/declarative/fx/qfxtextinput.cpp | 6 +- src/declarative/fx/qfxvisualitemmodel.cpp | 4 +- src/declarative/qml/parser/qmljs.g | 11 +- src/declarative/qml/parser/qmljsengine_p.cpp | 2 +- src/declarative/qml/parser/qmljsgrammar.cpp | 32 ++--- src/declarative/qml/parser/qmljsgrammar_p.h | 32 ++--- src/declarative/qml/parser/qmljsparser.cpp | 11 +- src/declarative/qml/qmlbinding.cpp | 3 +- src/declarative/qml/qmlcompiler.cpp | 151 ++++++++++----------- src/declarative/qml/qmlcompiler_p.h | 3 +- src/declarative/qml/qmlinfo.cpp | 53 +++----- src/declarative/qml/qmlinfo.h | 12 +- src/declarative/util/qmlanimation.cpp | 4 +- src/declarative/util/qmlpropertychanges.cpp | 6 +- .../data/unsupportedProperty.errors.txt | 2 +- 19 files changed, 171 insertions(+), 201 deletions(-) diff --git a/src/declarative/extra/qmlbehavior.cpp b/src/declarative/extra/qmlbehavior.cpp index e30bd39..f3eb014 100644 --- a/src/declarative/extra/qmlbehavior.cpp +++ b/src/declarative/extra/qmlbehavior.cpp @@ -77,7 +77,7 @@ void QmlBehavior::setAnimation(QmlAbstractAnimation *animation) { Q_D(QmlBehavior); if (d->animation) { - qmlInfo(this) << "Can't change the animation assigned to a Behavior."; + qmlInfo(tr("Can't change the animation assigned to a Behavior."),this); return; } diff --git a/src/declarative/extra/qmlxmllistmodel.cpp b/src/declarative/extra/qmlxmllistmodel.cpp index 01efa0e..fb26915 100644 --- a/src/declarative/extra/qmlxmllistmodel.cpp +++ b/src/declarative/extra/qmlxmllistmodel.cpp @@ -109,7 +109,7 @@ public: void setQuery(const QString &query) { if (query.startsWith(QLatin1Char('/'))) { - qmlInfo(this) << "An XmlRole query must not start with '/'"; + qmlInfo(tr("An XmlRole query must not start with '/'"),this); return; } m_query = query; @@ -545,7 +545,7 @@ void QmlXmlListModel::setQuery(const QString &query) { Q_D(QmlXmlListModel); if (!query.startsWith(QLatin1Char('/'))) { - qmlInfo(this) << "An XmlListModel query must start with '/' or \"//\""; + qmlInfo(tr("An XmlListModel query must start with '/' or \"//\""),this); return; } diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp index 64eaaaf..09776e5 100644 --- a/src/declarative/fx/qfxanchors.cpp +++ b/src/declarative/fx/qfxanchors.cpp @@ -334,7 +334,7 @@ void QFxAnchors::setFill(QFxItem *f) return; } if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){ - qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling."; + qmlInfo(tr("Can't anchor to an item that isn't a parent or sibling."), d->item); return; } d->remDepend(d->fill); @@ -359,7 +359,7 @@ void QFxAnchors::setCenterIn(QFxItem* c) return; } if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){ - qmlInfo(d->item) << "Can't anchor to an item that isn't a parent or sibling."; + qmlInfo(tr("Can't anchor to an item that isn't a parent or sibling."), d->item); return; } @@ -460,7 +460,7 @@ void QFxAnchorsPrivate::updateVerticalAnchors() --updatingVerticalAnchor; } else { // ### Make this certain :) - qmlInfo(item) << "Possible anchor loop detected on vertical anchor."; + qmlInfo(QFxAnchors::tr("Possible anchor loop detected on vertical anchor."), item); } } @@ -519,7 +519,7 @@ void QFxAnchorsPrivate::updateHorizontalAnchors() --updatingHorizontalAnchor; } else { // ### Make this certain :) - qmlInfo(item) << "Possible anchor loop detected on horizontal anchor."; + qmlInfo(QFxAnchors::tr("Possible anchor loop detected on horizontal anchor."), item); } } @@ -891,7 +891,7 @@ bool QFxAnchorsPrivate::checkHValid() const if (usedAnchors & QFxAnchors::HasLeftAnchor && usedAnchors & QFxAnchors::HasRightAnchor && usedAnchors & QFxAnchors::HasHCenterAnchor) { - qmlInfo(item) << "Can't specify left, right, and hcenter anchors."; + qmlInfo(QFxAnchors::tr("Can't specify left, right, and hcenter anchors."), item); return false; } @@ -901,16 +901,16 @@ bool QFxAnchorsPrivate::checkHValid() const bool QFxAnchorsPrivate::checkHAnchorValid(QFxAnchorLine anchor) const { if (!anchor.item) { - qmlInfo(item) << "Can't anchor to a null item."; + qmlInfo(QFxAnchors::tr("Can't anchor to a null item."), item); return false; } else if (anchor.anchorLine & QFxAnchorLine::Vertical_Mask) { - qmlInfo(item) << "Can't anchor a horizontal edge to a vertical edge."; + qmlInfo(QFxAnchors::tr("Can't anchor a horizontal edge to a vertical edge."), item); return false; } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){ - qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling."; + qmlInfo(QFxAnchors::tr("Can't anchor to an item that isn't a parent or sibling."), item); return false; } else if (anchor.item == item) { - qmlInfo(item) << "Can't anchor item to self."; + qmlInfo(QFxAnchors::tr("Can't anchor item to self."), item); return false; } @@ -922,13 +922,13 @@ bool QFxAnchorsPrivate::checkVValid() const if (usedAnchors & QFxAnchors::HasTopAnchor && usedAnchors & QFxAnchors::HasBottomAnchor && usedAnchors & QFxAnchors::HasVCenterAnchor) { - qmlInfo(item) << "Can't specify top, bottom, and vcenter anchors."; + qmlInfo(QFxAnchors::tr("Can't specify top, bottom, and vcenter anchors."), item); return false; } else if (usedAnchors & QFxAnchors::HasBaselineAnchor && (usedAnchors & QFxAnchors::HasTopAnchor || usedAnchors & QFxAnchors::HasBottomAnchor || usedAnchors & QFxAnchors::HasVCenterAnchor)) { - qmlInfo(item) << "Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors."; + qmlInfo(QFxAnchors::tr("Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors."), item); return false; } @@ -938,16 +938,16 @@ bool QFxAnchorsPrivate::checkVValid() const bool QFxAnchorsPrivate::checkVAnchorValid(QFxAnchorLine anchor) const { if (!anchor.item) { - qmlInfo(item) << "Can't anchor to a null item."; + qmlInfo(QFxAnchors::tr("Can't anchor to a null item."), item); return false; } else if (anchor.anchorLine & QFxAnchorLine::Horizontal_Mask) { - qmlInfo(item) << "Can't anchor a vertical edge to a horizontal edge."; + qmlInfo(QFxAnchors::tr("Can't anchor a vertical edge to a horizontal edge."), item); return false; } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){ - qmlInfo(item) << "Can't anchor to an item that isn't a parent or sibling."; + qmlInfo(QFxAnchors::tr("Can't anchor to an item that isn't a parent or sibling."), item); return false; } else if (anchor.item == item){ - qmlInfo(item) << "Can't anchor item to self."; + qmlInfo(QFxAnchors::tr("Can't anchor item to self."), item); return false; } diff --git a/src/declarative/fx/qfxflipable.cpp b/src/declarative/fx/qfxflipable.cpp index dc5101c..d381cfe 100644 --- a/src/declarative/fx/qfxflipable.cpp +++ b/src/declarative/fx/qfxflipable.cpp @@ -142,7 +142,7 @@ void QFxFlipable::setFront(QFxItem *front) { Q_D(QFxFlipable); if (d->front) { - qmlInfo(this) << "front is a write-once property"; + qmlInfo(tr("front is a write-once property"),this); return; } d->front = front; @@ -161,7 +161,7 @@ void QFxFlipable::setBack(QFxItem *back) { Q_D(QFxFlipable); if (d->back) { - qmlInfo(this) << "back is a write-once property"; + qmlInfo(tr("back is a write-once property"),this); return; } d->back = back; diff --git a/src/declarative/fx/qfxtextinput.cpp b/src/declarative/fx/qfxtextinput.cpp index 05d2260..f5bf911 100644 --- a/src/declarative/fx/qfxtextinput.cpp +++ b/src/declarative/fx/qfxtextinput.cpp @@ -508,7 +508,7 @@ void QFxTextInputPrivate::startCreatingCursor() q->connect(cursorComponent, SIGNAL(statusChanged(int)), q, SLOT(createCursor())); }else{//isError - qmlInfo(q) << "Could not load cursor delegate"; + qmlInfo(QFxTextInput::tr("Could not load cursor delegate"), q); qWarning() << cursorComponent->errors(); } } @@ -517,7 +517,7 @@ void QFxTextInput::createCursor() { Q_D(QFxTextInput); if(d->cursorComponent->isError()){ - qmlInfo(this) << "Could not load cursor delegate"; + qmlInfo(tr("Could not load cursor delegate"),this); qWarning() << d->cursorComponent->errors(); return; } @@ -529,7 +529,7 @@ void QFxTextInput::createCursor() delete d->cursorItem; d->cursorItem = qobject_cast(d->cursorComponent->create()); if(!d->cursorItem){ - qmlInfo(this) << "Could not instantiate cursor delegate"; + qmlInfo(tr("Could not instantiate cursor delegate"),this); //The failed instantiation should print its own error messages return; } diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index 3a9e5d4..a078da6 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -275,7 +275,7 @@ public: int count = object->metaObject()->propertyCount(); for (int ii = 1; ii < count; ++ii) { const QMetaProperty &prop = object->metaObject()->property(ii); - m_roleNames.insert(prop.name(), 0); + m_roleNames.insert(QString::fromUtf8(prop.name()), 0); } } } @@ -798,7 +798,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp } if (!item) { d->m_cache.releaseItem(nobj); - qmlInfo(d->m_delegate) << "Delegate component must be Item type."; + qmlInfo(QFxVisualDataModel::tr("Delegate component must be Item type."), d->m_delegate); } return item; diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g index 211887b..ed6c272 100644 --- a/src/declarative/qml/parser/qmljs.g +++ b/src/declarative/qml/parser/qmljs.g @@ -142,6 +142,7 @@ ****************************************************************************/ #include +#include #include @@ -2959,7 +2960,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; yylloc.startColumn += yylloc.length; yylloc.length = 0; - //const QString msg = QString::fromUtf8("Missing `;'"); + //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; @@ -2984,7 +2985,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { - const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + const QString msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; @@ -3012,7 +3013,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; @@ -3035,7 +3036,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; @@ -3048,7 +3049,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; } } - const QString msg = QString::fromUtf8("Syntax error"); + const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } diff --git a/src/declarative/qml/parser/qmljsengine_p.cpp b/src/declarative/qml/parser/qmljsengine_p.cpp index 7d4d6d7..32068c0 100644 --- a/src/declarative/qml/parser/qmljsengine_p.cpp +++ b/src/declarative/qml/parser/qmljsengine_p.cpp @@ -164,7 +164,7 @@ double integerFromString(const char *buf, int size, int radix) double integerFromString(const QString &str, int radix) { - QByteArray ba = str.trimmed().toUtf8(); + QByteArray ba = str.trimmed().toLatin1(); return integerFromString(ba.constData(), ba.size(), radix); } diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp index 67f1403..da3ce2a 100644 --- a/src/declarative/qml/parser/qmljsgrammar.cpp +++ b/src/declarative/qml/parser/qmljsgrammar.cpp @@ -2,8 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -11,8 +10,8 @@ ** 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 Technology Preview License Agreement accompanying -** this package. +** 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 @@ -22,20 +21,21 @@ ** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** +** 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$ ** ****************************************************************************/ diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h index 7de77c0..b297f81 100644 --- a/src/declarative/qml/parser/qmljsgrammar_p.h +++ b/src/declarative/qml/parser/qmljsgrammar_p.h @@ -2,8 +2,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -11,8 +10,8 @@ ** 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 Technology Preview License Agreement accompanying -** this package. +** 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 @@ -22,20 +21,21 @@ ** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** +** 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$ ** ****************************************************************************/ diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp index e805ce5..2c8162b 100644 --- a/src/declarative/qml/parser/qmljsparser.cpp +++ b/src/declarative/qml/parser/qmljsparser.cpp @@ -42,6 +42,7 @@ ****************************************************************************/ #include +#include #include @@ -1723,7 +1724,7 @@ case 337: { yylloc.startColumn += yylloc.length; yylloc.length = 0; - //const QString msg = QString::fromUtf8("Missing `;'"); + //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; @@ -1748,7 +1749,7 @@ case 337: { token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { - const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + const QString msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; @@ -1776,7 +1777,7 @@ case 337: { for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; @@ -1799,7 +1800,7 @@ case 337: { int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { - const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; @@ -1812,7 +1813,7 @@ case 337: { } } - const QString msg = QString::fromUtf8("Syntax error"); + const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 2435c40..6a70c1e 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -134,8 +134,7 @@ void QmlBinding::update(QmlMetaProperty::WriteFlags flags) data->updating = false; } else { - qmlInfo(data->property.object()) << "Binding loop detected for property" - << data->property.name(); + qmlInfo(tr("Binding loop detected for property \"%1\"").arg(data->property.name()), data->property.object()); } data->release(); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 431f9f6..fa7e473 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -157,7 +157,7 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) For example: \code - COMPILE_EXCEPTION(property, "Error for property" << property->name); + COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(QString::fromUtf8(property->name))); \endcode */ #define COMPILE_EXCEPTION(token, desc) \ @@ -167,9 +167,7 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) error.setUrl(output->url); \ error.setLine((token)->location.start.line); \ error.setColumn((token)->location.start.column); \ - QDebug d(&exceptionDescription); \ - d << desc; \ - error.setDescription(exceptionDescription.trimmed()); \ + error.setDescription(desc.trimmed()); \ exceptions << error; \ return false; \ } @@ -195,7 +193,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, "Invalid property assignment:" << QString::fromUtf8(prop.name()) << "is a read-only property"); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); if (prop.isEnumType()) { int value; @@ -204,7 +202,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, } else value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) - COMPILE_EXCEPTION(v, "Invalid property assignment: unknown enumeration"); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration")); return true; } int type = prop.userType(); @@ -212,61 +210,61 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, case -1: break; case QVariant::String: - if (!v->value.isString()) COMPILE_EXCEPTION(v, "Invalid property assignment: string expected"); + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected")); break; case QVariant::Url: - if (!v->value.isString()) COMPILE_EXCEPTION(v, "Invalid property assignment: url expected"); + if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected")); break; case QVariant::UInt: { bool ok; string.toUInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: unsigned int expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected")); } break; case QVariant::Int: { bool ok; string.toInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: int expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected")); } break; case QMetaType::Float: { bool ok; string.toFloat(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: float expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected")); } break; case QVariant::Double: { bool ok; string.toDouble(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, "Invalid property assignment: double expected"); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected")); } break; case QVariant::Color: { QColor c = QmlStringConverters::colorFromString(string); - if (!c.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: color expected"); + if (!c.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); } break; case QVariant::Date: { QDate d = QDate::fromString(string, Qt::ISODate); - if (!d.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: date expected"); + if (!d.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); } break; case QVariant::Time: { QTime time = QTime::fromString(string, Qt::ISODate); - if (!time.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: time expected"); + if (!time.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected")); } break; case QVariant::DateTime: { QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); - if (!dateTime.isValid()) COMPILE_EXCEPTION(v, "Invalid property assignment: datetime expected"); + if (!dateTime.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); } break; case QVariant::Point: @@ -274,7 +272,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QPointF point = QmlStringConverters::pointFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: point expected"); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected")); } break; case QVariant::Size: @@ -282,7 +280,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QSizeF size = QmlStringConverters::sizeFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: size expected"); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected")); } break; case QVariant::Rect: @@ -290,19 +288,19 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QRectF rect = QmlStringConverters::rectFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: rect expected"); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected")); } break; case QVariant::Bool: { - if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, "Invalid property assignment: boolean expected"); + if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected")); } break; case QVariant::Vector3D: { bool ok; QVector3D point = QmlStringConverters::vector3DFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, "Invalid property assignment: 3D vector expected"); + if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); } break; default: @@ -313,7 +311,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(t); if (!converter) - COMPILE_EXCEPTION(v, "Invalid property assignment: unknown type" << prop.type()); + COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); } break; } @@ -741,7 +739,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) } if (canDefer && !deferredList.isEmpty() && - deferredList.contains(prop->name)) + deferredList.contains(QString::fromUtf8(prop->name))) prop->isDeferred = true; } @@ -766,7 +764,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) } if (canDefer && !deferredList.isEmpty() && - deferredList.contains(prop->name)) + deferredList.contains(QString::fromUtf8(prop->name))) prop->isDeferred = true; } @@ -1025,18 +1023,18 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, if (obj->properties.count() > 1 || (obj->properties.count() == 1 && obj->properties.begin().key() != "id") || !obj->scriptBlockObjects.isEmpty()) - COMPILE_EXCEPTION(obj, "Invalid component specification"); + COMPILE_EXCEPTION(obj, tr("Invalid component specification")); if (obj->properties.count()) idProp = *obj->properties.begin(); if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive()))) - COMPILE_EXCEPTION(obj, "Invalid component id specification"); + COMPILE_EXCEPTION(obj, tr("Invalid component id specification")); if (idProp) { QString idVal = idProp->values.first()->primitive(); if (compileState.ids.contains(idVal)) - COMPILE_EXCEPTION(obj, "id is not unique"); + COMPILE_EXCEPTION(obj, tr("id is not unique")); obj->id = idVal; addId(idVal, obj); @@ -1046,14 +1044,14 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, if (obj->defaultProperty && (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 || (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) - COMPILE_EXCEPTION(obj, "Invalid component body specification"); + COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); Object *root = 0; if (obj->defaultProperty && obj->defaultProperty->values.count()) root = obj->defaultProperty->values.first()->object; if (!root) - COMPILE_EXCEPTION(obj, "Cannot create empty component specification"); + COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification")); // Build the component tree COMPILE_CHECK(buildComponentFromRoot(root, ctxt)); @@ -1072,11 +1070,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) Property *source = *script->properties.begin(); if (script->defaultProperty) - COMPILE_EXCEPTION(source, "Invalid Script block. Specify either the source property or inline script."); + COMPILE_EXCEPTION(source, tr("Invalid Script block. Specify either the source property or inline script.")); if (source->value || source->values.count() != 1 || source->values.at(0)->object || !source->values.at(0)->value.isString()) - COMPILE_EXCEPTION(source, "Invalid Script source value"); + COMPILE_EXCEPTION(source, tr("Invalid Script source value")); sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); @@ -1088,7 +1086,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } else if (!script->properties.isEmpty()) { - COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); + COMPILE_EXCEPTION(*script->properties.begin(), tr("Properties cannot be set on Script block")); } else if (script->defaultProperty) { sourceUrl = output->url.toString(); @@ -1099,7 +1097,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) if (lineNumber == 1) lineNumber = v->location.start.line; if (v->object || !v->value.isString()) - COMPILE_EXCEPTION(v, "Invalid Script block"); + COMPILE_EXCEPTION(v, tr("Invalid Script block")); if (ii == 0) { currentLocation = v->location.start; @@ -1205,7 +1203,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, Q_ASSERT(obj->metaObject()); if (prop->isEmpty()) - COMPILE_EXCEPTION(prop, "Empty property assignment"); + COMPILE_EXCEPTION(prop, tr("Empty property assignment")); QByteArray name = prop->name; Q_ASSERT(name.startsWith("on")); @@ -1224,7 +1222,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, } else { if (prop->value || prop->values.count() > 1) - COMPILE_EXCEPTION(prop, "Incorrectly specified signal"); + COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal")); prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1269,7 +1267,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, const BindingContext &ctxt) { if (prop->isEmpty()) - COMPILE_EXCEPTION(prop, "Empty property assignment"); + COMPILE_EXCEPTION(prop, tr("Empty property assignment")); const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); @@ -1281,7 +1279,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, // Attached properties cannot be used on sub-objects. Sub-objects // always exist in a binding sub-context, which is what we test // for here. - COMPILE_EXCEPTION(prop, "Attached properties cannot be used here"); + COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); } QmlType *type = 0; @@ -1296,11 +1294,11 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, ctxt)); return true; } else if (!type || !type->attachedPropertiesType()) { - COMPILE_EXCEPTION(prop, "Non-existant attached object"); + COMPILE_EXCEPTION(prop, tr("Non-existant attached object")); } if (!prop->value) - COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1358,9 +1356,9 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } else if (prop->index == -1) { if (prop->isDefault) { - COMPILE_EXCEPTION(prop->values.first(), "Cannot assign to non-existant default property"); + COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existant default property")); } else { - COMPILE_EXCEPTION(prop, "Cannot assign to non-existant property" << prop->name); + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); } } else if (prop->value) { @@ -1388,12 +1386,12 @@ QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, const BindingContext &ctxt) { if (!nsProp->value) - COMPILE_EXCEPTION(nsProp, "Invalid use of namespace"); + COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace")); foreach (Property *prop, nsProp->value->properties) { if (!isAttachedPropertyName(prop->name)) - COMPILE_EXCEPTION(prop, "Not an attached property name"); + COMPILE_EXCEPTION(prop, tr("Not an attached property name")); // Setup attached property data @@ -1402,10 +1400,10 @@ QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) - COMPILE_EXCEPTION(prop, "Non-existant attached object"); + COMPILE_EXCEPTION(prop, tr("Non-existant attached object")); if (!prop->value) - COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); + COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1577,13 +1575,13 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, if (prop->value || prop->values.count() > 1 || prop->values.at(0)->object) - COMPILE_EXCEPTION(prop, "Invalid use of id property"); + COMPILE_EXCEPTION(prop, tr("Invalid use of id property")); QmlParser::Value *idValue = prop->values.at(0); QString val = idValue->primitive(); if (!isValidId(val)) - COMPILE_EXCEPTION(prop, val << "is not a valid object id"); + COMPILE_EXCEPTION(prop, tr("\"%1\" is not a valid object id").arg(val)); // We disallow id's that conflict with import prefixes and types QmlEnginePrivate::ImportedNamespace *ns = 0; @@ -1591,12 +1589,12 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), &type, 0, 0, 0, &ns); if (type) - COMPILE_EXCEPTION(idValue, "id conflicts with type name"); + COMPILE_EXCEPTION(idValue, tr("id conflicts with type name")); if (ns) - COMPILE_EXCEPTION(idValue, "id conflicts with namespace prefix"); + COMPILE_EXCEPTION(idValue, tr("id conflicts with namespace prefix")); if (compileState.ids.contains(val)) - COMPILE_EXCEPTION(prop, "id is not unique"); + COMPILE_EXCEPTION(prop, tr("id is not unique")); prop->values.at(0)->type = Value::Id; @@ -1677,7 +1675,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { - COMPILE_EXCEPTION(prop, "Invalid property access"); + COMPILE_EXCEPTION(prop, tr("Invalid property access")); } } else { @@ -1685,8 +1683,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value->metatype = QmlEnginePrivate::get(engine)->metaObjectForType(prop->type); if (!prop->value->metatype) - COMPILE_EXCEPTION(prop, "Cannot nest non-QObject property" << - prop->name); + COMPILE_EXCEPTION(prop, tr("Cannot nest non-QObject property \"%1\"").arg(QString::fromUtf8(prop->name))); obj->addGroupedProperty(prop); @@ -1702,19 +1699,19 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, const BindingContext &ctxt) { if (obj->defaultProperty) - COMPILE_EXCEPTION(obj, "Invalid property use"); + COMPILE_EXCEPTION(obj, tr("Invalid property use")); obj->metatype = type->metaObject(); foreach (Property *prop, obj->properties) { int idx = type->metaObject()->indexOfProperty(prop->name.constData()); if (idx == -1) - COMPILE_EXCEPTION(prop, "Cannot assign to non-existant property" << prop->name); + COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); QMetaProperty p = type->metaObject()->property(idx); prop->index = idx; prop->type = p.userType(); if (prop->value || prop->values.count() != 1) - COMPILE_EXCEPTION(prop, "Invalid property use"); + COMPILE_EXCEPTION(prop, tr("Invalid property use")); Value *value = prop->values.at(0); @@ -1722,7 +1719,7 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; if (!isPropertyValue && !isPropertyInterceptor) { - COMPILE_EXCEPTION(prop, "Invalid property use"); + COMPILE_EXCEPTION(prop, tr("Invalid property use")); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); @@ -1780,12 +1777,12 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, "Cannot assign object to list"); + COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); } } } else { - COMPILE_EXCEPTION(v, "Cannot assign primitives to lists"); + COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); } } @@ -1804,19 +1801,19 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, "Cannot assign object to list"); + COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); } } } else if (v->value.isScript()) { if (assignedBinding) - COMPILE_EXCEPTION(v, "Can only assign one binding to lists"); + COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists")); assignedBinding = true; COMPILE_CHECK(buildBinding(v, prop, ctxt)); v->type = Value::PropertyBinding; } else { - COMPILE_EXCEPTION(v, "Cannot assign primitives to lists"); + COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); } } @@ -1944,7 +1941,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, buildDynamicMeta(prop->parent, ForceCreation); v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { - COMPILE_EXCEPTION(v->object, "Cannot assign object to property"); + COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property")); } } @@ -1989,12 +1986,12 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) if (prop.isDefaultProperty) { if (seenDefaultProperty) - COMPILE_EXCEPTION(obj, "Duplicate default property"); + COMPILE_EXCEPTION(obj, tr("Duplicate default property")); seenDefaultProperty = true; } if (propNames.contains(prop.name)) - COMPILE_EXCEPTION(obj, "Duplicate property name"); + COMPILE_EXCEPTION(obj, tr("Duplicate property name")); propNames.insert(prop.name); } @@ -2002,13 +1999,13 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { QByteArray name = obj->dynamicSignals.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, "Duplicate signal name"); + COMPILE_EXCEPTION(obj, tr("Duplicate signal name")); methodNames.insert(name); } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { QByteArray name = obj->dynamicSlots.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, "Duplicate method name"); + COMPILE_EXCEPTION(obj, tr("Duplicate method name")); methodNames.insert(name); } @@ -2030,7 +2027,7 @@ bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj) property = obj->getProperty(p.name); if (property->value) - COMPILE_EXCEPTION(property, "Invalid property nesting"); + COMPILE_EXCEPTION(property, tr("Invalid property nesting")); for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) { Value *v = p.defaultValue->values.at(ii); @@ -2076,7 +2073,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) if (-1 != propIdx) { QMetaProperty prop = obj->metaObject()->property(propIdx); if (prop.isFinal()) - COMPILE_EXCEPTION(&p, "Cannot override FINAL property"); + COMPILE_EXCEPTION(&p, tr("Cannot override FINAL property")); } if (p.isDefaultProperty && @@ -2101,7 +2098,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) QmlEnginePrivate *priv = QmlEnginePrivate::get(engine); if (!priv->resolveType(unit->imports, p.customType, &qmltype, &url, 0, 0, 0)) - COMPILE_EXCEPTION(&p, "Invalid property type"); + COMPILE_EXCEPTION(&p, tr("Invalid property type")); if (!qmltype) { QmlCompositeTypeData *tdata = priv->typeManager.get(url); @@ -2260,24 +2257,24 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, const Object::DynamicProperty &prop) { if (!prop.defaultValue) - COMPILE_EXCEPTION(obj, "No property alias location"); + COMPILE_EXCEPTION(obj, tr("No property alias location")); if (prop.defaultValue->values.count() != 1 || prop.defaultValue->values.at(0)->object || !prop.defaultValue->values.at(0)->value.isScript()) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); QmlJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST(); if (!node) - COMPILE_EXCEPTION(obj, "No property alias location"); // ### Can this happen? + COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen? QStringList alias = astNodeToStringList(node); if (alias.count() != 1 && alias.count() != 2) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); if (!compileState.ids.contains(alias.at(0))) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); Object *idObject = compileState.ids[alias.at(0)]; @@ -2289,7 +2286,7 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); writable = aliasProperty.isWritable(); @@ -2324,7 +2321,7 @@ bool QmlCompiler::buildBinding(QmlParser::Value *value, QMetaProperty mp = prop->parent->metaObject()->property(prop->index); if (!mp.isWritable() && !QmlMetaType::isList(prop->type)) - COMPILE_EXCEPTION(prop, "Invalid property assignment:" << QString::fromLatin1(prop->name) << "is a read-only property"); + COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); BindingReference reference; reference.expression = value->value; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index ecf3344..6d6a25e 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -135,8 +135,9 @@ private: }; class QMetaObjectBuilder; -class Q_DECLARATIVE_EXPORT QmlCompiler +class Q_DECLARATIVE_EXPORT QmlCompiler : public QObject { + Q_OBJECT public: QmlCompiler(); diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index e3c0225..75de985 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -42,18 +42,19 @@ #include "qmlinfo.h" #include #include +#include QT_BEGIN_NAMESPACE /*! - \class QmlInfo - \brief The QmlInfo class prints warnings messages that include the file and line number for QML types. + \fn void qmlInfo(const QString& message, QObject *object) + + \brief Prints warnings messages that include the file and line number for QML types. When QML types display warning messages, it improves tracibility if they include the QML file and line number on which the particular instance was instantiated. - QmlInfo statements work just like regular Qt qDebug() statements. To include the file and line number, an object must be passed. If the file and line number is not available for that instance (either it was not instantiated by the QML engine or location @@ -62,7 +63,7 @@ QT_BEGIN_NAMESPACE For example, \code - qmlInfo(this) << "component property is a write-once property"; + qmlInfo(object, tr("component property is a write-once property")); \endcode prints @@ -72,46 +73,26 @@ QT_BEGIN_NAMESPACE \endcode */ -/*! - Construct a QmlInfo, using \a object for file and line number - information. -*/ -QmlInfo::QmlInfo(QObject *object) -: QDebug(QtWarningMsg) +void qmlInfo(const QString& msg, QObject* object) { - *this << "QML"; - if (object) - *this << object->metaObject()->className(); + QString pos = QLatin1String("QML ") + QLatin1String(object->metaObject()->className()); QmlDeclarativeData *ddata = QmlDeclarativeData::get(object); + pos += QLatin1String("("); if (ddata) { - QString location = QLatin1String("("); if (ddata->outerContext) { - location += ddata->outerContext->baseUrl().toString(); + pos += ddata->outerContext->baseUrl().toString(); } else { - location += "unknown"; + pos += qApp->translate("QmlInfo","unknown"); } - location += QLatin1String(":"); - location += QString::number(ddata->lineNumber); - location += QLatin1String(":"); - location += QString::number(ddata->columnNumber); - location += QLatin1String(")"); - *this << qPrintable(location); + pos += QLatin1String(":"); + pos += QString::number(ddata->lineNumber); + pos += QLatin1String(":"); + pos += QString::number(ddata->columnNumber); } else { - *this << "(unknown location):"; + pos += qApp->translate("QmlInfo","unknown location"); } + pos += QLatin1String(")"); + qWarning((pos + msg).toLocal8Bit()); // XXX allow other processing? } -/*! - The destructor does nothing special. -*/ -QmlInfo::~QmlInfo() -{ -} - -/*! - \relates QmlInfo - \fn QmlInfo qmlInfo(QObject *me) - Constructs an instance of QmlInfo from \a me and returns it. -*/ - QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h index da8144c..f2d17fe 100644 --- a/src/declarative/qml/qmlinfo.h +++ b/src/declarative/qml/qmlinfo.h @@ -50,17 +50,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class Q_DECLARATIVE_EXPORT QmlInfo : public QDebug -{ -public: - QmlInfo(QObject *); - ~QmlInfo(); -}; - -Q_DECLARATIVE_EXPORT inline QmlInfo qmlInfo(QObject *me) -{ - return QmlInfo(me); -} +Q_DECLARATIVE_EXPORT void qmlInfo(const QString& msg, QObject *me=0); QT_END_NAMESPACE diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index a8de8d5..f42aa4e 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -224,10 +224,10 @@ QmlMetaProperty QmlAbstractAnimationPrivate::createProperty(QObject *obj, const Q_Q(QmlAbstractAnimation); QmlMetaProperty prop = QmlMetaProperty::createProperty(obj, str); if (!prop.isValid()) { - qmlInfo(q) << "Cannot animate non-existant property" << str; + qmlInfo(QmlAbstractAnimation::tr("Cannot animate non-existant property \"%1\"").arg(str), q); return QmlMetaProperty(); } else if (!prop.isWritable()) { - qmlInfo(q) << "Cannot animate read-only property" << str; + qmlInfo(QmlAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str), q); return QmlMetaProperty(); } return prop; diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp index b07a79f..a112245 100644 --- a/src/declarative/util/qmlpropertychanges.cpp +++ b/src/declarative/util/qmlpropertychanges.cpp @@ -303,12 +303,12 @@ QmlMetaProperty QmlPropertyChangesPrivate::property(const QByteArray &property) { Q_Q(QmlPropertyChanges); - QmlMetaProperty prop = QmlMetaProperty::createProperty(object, QString::fromLatin1(property)); + QmlMetaProperty prop = QmlMetaProperty::createProperty(object, QString::fromUtf8(property)); if (!prop.isValid()) { - qmlInfo(q) << "Cannot assign to non-existant property" << property; + qmlInfo(QmlPropertyChanges::tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(property)), q); return QmlMetaProperty(); } else if (!prop.isWritable()) { - qmlInfo(q) << "Cannot assign to read-only property" << property; + qmlInfo(QmlPropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(QString::fromUtf8(property)), q); return QmlMetaProperty(); } return prop; diff --git a/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt index 3a90a7d..3cd626d 100644 --- a/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt +++ b/tests/auto/declarative/qmllanguage/data/unsupportedProperty.errors.txt @@ -1 +1 @@ -3:13:Invalid property assignment: unknown type QVariant::QMatrix +3:13:Invalid property assignment: unsupported type "QMatrix" -- cgit v0.12 From 7aa4e177bbc01b7385cb345f3ad620a935dbe2d4 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 13 Oct 2009 13:06:50 +1000 Subject: i18n --- src/declarative/qml/parser/qmljs.g | 2 +- src/declarative/qml/parser/qmljslexer.cpp | 20 +-- src/declarative/qml/parser/qmljsparser.cpp | 2 +- src/declarative/qml/qmlcompiler.cpp | 143 +++++++++++---------- src/declarative/qml/qmlcompiler_p.h | 3 +- src/declarative/qml/qmlinfo.cpp | 10 +- src/declarative/qml/qmlvme.cpp | 29 ++--- tests/auto/declarative/anchors/tst_anchors.cpp | 12 +- .../auto/declarative/animations/tst_animations.cpp | 2 +- .../qmlecmascript/tst_qmlecmascript.cpp | 2 +- 10 files changed, 114 insertions(+), 111 deletions(-) diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g index ed6c272..eb9a8ab 100644 --- a/src/declarative/qml/parser/qmljs.g +++ b/src/declarative/qml/parser/qmljs.g @@ -142,7 +142,7 @@ ****************************************************************************/ #include -#include +#include #include diff --git a/src/declarative/qml/parser/qmljslexer.cpp b/src/declarative/qml/parser/qmljslexer.cpp index 54f8d78..2c03c21 100644 --- a/src/declarative/qml/parser/qmljslexer.cpp +++ b/src/declarative/qml/parser/qmljslexer.cpp @@ -48,6 +48,8 @@ #include "qmljslexer_p.h" #include "qmljsgrammar_p.h" +#include + #include #include #include @@ -548,7 +550,7 @@ int Lexer::lex() else { setDone(Bad); err = IllegalCharacter; - errmsg = QLatin1String("Illegal character"); + errmsg = qApp->translate("QmlParser", "Illegal character"); } } break; @@ -562,7 +564,7 @@ int Lexer::lex() } else if (current == 0 || isLineTerminator()) { setDone(Bad); err = UnclosedStringLiteral; - errmsg = QLatin1String("Unclosed string at end of line"); + errmsg = qApp->translate("QmlParser", "Unclosed string at end of line"); } else if (current == '\\') { state = InEscapeSequence; } else { @@ -588,7 +590,7 @@ int Lexer::lex() } else { setDone(Bad); err = IllegalEscapeSequence; - errmsg = QLatin1String("Illegal escape squence"); + errmsg = qApp->translate("QmlParser", "Illegal escape squence"); } } else if (current == 'x') state = InHexEscape; @@ -634,7 +636,7 @@ int Lexer::lex() } else { setDone(Bad); err = IllegalUnicodeEscapeSequence; - errmsg = QLatin1String("Illegal unicode escape sequence"); + errmsg = qApp->translate("QmlParser", "Illegal unicode escape sequence"); } break; case InSingleLineComment: @@ -660,7 +662,7 @@ int Lexer::lex() if (current == 0) { setDone(Bad); err = UnclosedComment; - errmsg = QLatin1String("Unclosed comment at end of file"); + errmsg = qApp->translate("QmlParser", "Unclosed comment at end of file"); driver->addComment(startpos, tokenLength(), startlineno, startcolumn); } else if (isLineTerminator()) { shiftWindowsLineBreak(); @@ -747,7 +749,7 @@ int Lexer::lex() } else { setDone(Bad); err = IllegalExponentIndicator; - errmsg = QLatin1String("Illegal syntax for exponential number"); + errmsg = qApp->translate("QmlParser", "Illegal syntax for exponential number"); } break; case InExponent: @@ -773,7 +775,7 @@ int Lexer::lex() && isIdentLetter(current)) { state = Bad; err = IllegalIdentifier; - errmsg = QLatin1String("Identifier cannot start with numeric literal"); + errmsg = qApp->translate("QmlParser", "Identifier cannot start with numeric literal"); } // terminate string @@ -1104,7 +1106,7 @@ bool Lexer::scanRegExp(RegExpBodyPrefix prefix) while (1) { if (isLineTerminator() || current == 0) { - errmsg = QLatin1String("Unterminated regular expression literal"); + errmsg = qApp->translate("QmlParser", "Unterminated regular expression literal"); return false; } else if (current != '/' || lastWasEscape == true) @@ -1128,7 +1130,7 @@ bool Lexer::scanRegExp(RegExpBodyPrefix prefix) while (isIdentLetter(current)) { int flag = Ecma::RegExp::flagFromChar(current); if (flag == 0) { - errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") + errmsg = qApp->translate("QmlParser", "Invalid regular expression flag '%0'") .arg(QChar(current)); return false; } diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp index 2c8162b..402aaeb 100644 --- a/src/declarative/qml/parser/qmljsparser.cpp +++ b/src/declarative/qml/parser/qmljsparser.cpp @@ -42,7 +42,7 @@ ****************************************************************************/ #include -#include +#include #include diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index fa7e473..c744509 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include "private/qmlcustomparser_p_p.h" #include #include @@ -157,7 +158,7 @@ bool QmlCompiler::isSignalPropertyName(const QByteArray &name) For example: \code - COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(QString::fromUtf8(property->name))); + COMPILE_EXCEPTION(property, qApp->translate("QmlCompiler","Error for property \"%1\"").arg(QString::fromUtf8(property->name))); \endcode */ #define COMPILE_EXCEPTION(token, desc) \ @@ -193,7 +194,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name()))); if (prop.isEnumType()) { int value; @@ -202,7 +203,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, } else value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unknown enumeration")); return true; } int type = prop.userType(); @@ -210,61 +211,61 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, case -1: break; case QVariant::String: - if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected")); + if (!v->value.isString()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: string expected")); break; case QVariant::Url: - if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected")); + if (!v->value.isString()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: url expected")); break; case QVariant::UInt: { bool ok; string.toUInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unsigned int expected")); } break; case QVariant::Int: { bool ok; string.toInt(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: int expected")); } break; case QMetaType::Float: { bool ok; string.toFloat(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: float expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: float expected")); } break; case QVariant::Double: { bool ok; string.toDouble(&ok); - if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: double expected")); + if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: double expected")); } break; case QVariant::Color: { QColor c = QmlStringConverters::colorFromString(string); - if (!c.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected")); + if (!c.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: color expected")); } break; case QVariant::Date: { QDate d = QDate::fromString(string, Qt::ISODate); - if (!d.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected")); + if (!d.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: date expected")); } break; case QVariant::Time: { QTime time = QTime::fromString(string, Qt::ISODate); - if (!time.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected")); + if (!time.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: time expected")); } break; case QVariant::DateTime: { QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate); - if (!dateTime.isValid()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected")); + if (!dateTime.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: datetime expected")); } break; case QVariant::Point: @@ -272,7 +273,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QPointF point = QmlStringConverters::pointFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected")); + if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: point expected")); } break; case QVariant::Size: @@ -280,7 +281,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QSizeF size = QmlStringConverters::sizeFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected")); + if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: size expected")); } break; case QVariant::Rect: @@ -288,19 +289,19 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, { bool ok; QRectF rect = QmlStringConverters::rectFFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected")); + if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: rect expected")); } break; case QVariant::Bool: { - if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected")); + if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: boolean expected")); } break; case QVariant::Vector3D: { bool ok; QVector3D point = QmlStringConverters::vector3DFromString(string, &ok); - if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected")); + if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: 3D vector expected")); } break; default: @@ -311,7 +312,7 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QmlMetaType::StringConverter converter = QmlMetaType::customStringConverter(t); if (!converter) - COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type())))); } break; } @@ -1023,18 +1024,18 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, if (obj->properties.count() > 1 || (obj->properties.count() == 1 && obj->properties.begin().key() != "id") || !obj->scriptBlockObjects.isEmpty()) - COMPILE_EXCEPTION(obj, tr("Invalid component specification")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component specification")); if (obj->properties.count()) idProp = *obj->properties.begin(); if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive()))) - COMPILE_EXCEPTION(obj, tr("Invalid component id specification")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component id specification")); if (idProp) { QString idVal = idProp->values.first()->primitive(); if (compileState.ids.contains(idVal)) - COMPILE_EXCEPTION(obj, tr("id is not unique")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","id is not unique")); obj->id = idVal; addId(idVal, obj); @@ -1044,14 +1045,14 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, if (obj->defaultProperty && (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 || (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) - COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component body specification")); Object *root = 0; if (obj->defaultProperty && obj->defaultProperty->values.count()) root = obj->defaultProperty->values.first()->object; if (!root) - COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Cannot create empty component specification")); // Build the component tree COMPILE_CHECK(buildComponentFromRoot(root, ctxt)); @@ -1070,11 +1071,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) Property *source = *script->properties.begin(); if (script->defaultProperty) - COMPILE_EXCEPTION(source, tr("Invalid Script block. Specify either the source property or inline script.")); + COMPILE_EXCEPTION(source, qApp->translate("QmlCompiler","Invalid Script block. Specify either the source property or inline script.")); if (source->value || source->values.count() != 1 || source->values.at(0)->object || !source->values.at(0)->value.isString()) - COMPILE_EXCEPTION(source, tr("Invalid Script source value")); + COMPILE_EXCEPTION(source, qApp->translate("QmlCompiler","Invalid Script source value")); sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); @@ -1086,7 +1087,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } else if (!script->properties.isEmpty()) { - COMPILE_EXCEPTION(*script->properties.begin(), tr("Properties cannot be set on Script block")); + COMPILE_EXCEPTION(*script->properties.begin(), qApp->translate("QmlCompiler","Properties cannot be set on Script block")); } else if (script->defaultProperty) { sourceUrl = output->url.toString(); @@ -1097,7 +1098,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) if (lineNumber == 1) lineNumber = v->location.start.line; if (v->object || !v->value.isString()) - COMPILE_EXCEPTION(v, tr("Invalid Script block")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid Script block")); if (ii == 0) { currentLocation = v->location.start; @@ -1203,7 +1204,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, Q_ASSERT(obj->metaObject()); if (prop->isEmpty()) - COMPILE_EXCEPTION(prop, tr("Empty property assignment")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Empty property assignment")); QByteArray name = prop->name; Q_ASSERT(name.startsWith("on")); @@ -1222,7 +1223,7 @@ bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, } else { if (prop->value || prop->values.count() > 1) - COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Incorrectly specified signal")); prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1267,7 +1268,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, const BindingContext &ctxt) { if (prop->isEmpty()) - COMPILE_EXCEPTION(prop, tr("Empty property assignment")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Empty property assignment")); const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); @@ -1279,7 +1280,7 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, // Attached properties cannot be used on sub-objects. Sub-objects // always exist in a binding sub-context, which is what we test // for here. - COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Attached properties cannot be used here")); } QmlType *type = 0; @@ -1294,11 +1295,11 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, ctxt)); return true; } else if (!type || !type->attachedPropertiesType()) { - COMPILE_EXCEPTION(prop, tr("Non-existant attached object")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Non-existant attached object")); } if (!prop->value) - COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1356,9 +1357,9 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } else if (prop->index == -1) { if (prop->isDefault) { - COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existant default property")); + COMPILE_EXCEPTION(prop->values.first(), qApp->translate("QmlCompiler","Cannot assign to non-existant default property")); } else { - COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); } } else if (prop->value) { @@ -1386,12 +1387,12 @@ QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, const BindingContext &ctxt) { if (!nsProp->value) - COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace")); + COMPILE_EXCEPTION(nsProp, qApp->translate("QmlCompiler","Invalid use of namespace")); foreach (Property *prop, nsProp->value->properties) { if (!isAttachedPropertyName(prop->name)) - COMPILE_EXCEPTION(prop, tr("Not an attached property name")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Not an attached property name")); // Setup attached property data @@ -1400,10 +1401,10 @@ QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) - COMPILE_EXCEPTION(prop, tr("Non-existant attached object")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Non-existant attached object")); if (!prop->value) - COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); prop->index = type->index(); @@ -1575,13 +1576,13 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, if (prop->value || prop->values.count() > 1 || prop->values.at(0)->object) - COMPILE_EXCEPTION(prop, tr("Invalid use of id property")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid use of id property")); QmlParser::Value *idValue = prop->values.at(0); QString val = idValue->primitive(); if (!isValidId(val)) - COMPILE_EXCEPTION(prop, tr("\"%1\" is not a valid object id").arg(val)); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","\"%1\" is not a valid object id").arg(val)); // We disallow id's that conflict with import prefixes and types QmlEnginePrivate::ImportedNamespace *ns = 0; @@ -1589,12 +1590,12 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), &type, 0, 0, 0, &ns); if (type) - COMPILE_EXCEPTION(idValue, tr("id conflicts with type name")); + COMPILE_EXCEPTION(idValue, qApp->translate("QmlCompiler","id conflicts with type name")); if (ns) - COMPILE_EXCEPTION(idValue, tr("id conflicts with namespace prefix")); + COMPILE_EXCEPTION(idValue, qApp->translate("QmlCompiler","id conflicts with namespace prefix")); if (compileState.ids.contains(val)) - COMPILE_EXCEPTION(prop, tr("id is not unique")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","id is not unique")); prop->values.at(0)->type = Value::Id; @@ -1675,7 +1676,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { - COMPILE_EXCEPTION(prop, tr("Invalid property access")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property access")); } } else { @@ -1683,7 +1684,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value->metatype = QmlEnginePrivate::get(engine)->metaObjectForType(prop->type); if (!prop->value->metatype) - COMPILE_EXCEPTION(prop, tr("Cannot nest non-QObject property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot nest non-QObject property \"%1\"").arg(QString::fromUtf8(prop->name))); obj->addGroupedProperty(prop); @@ -1699,19 +1700,19 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, const BindingContext &ctxt) { if (obj->defaultProperty) - COMPILE_EXCEPTION(obj, tr("Invalid property use")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid property use")); obj->metatype = type->metaObject(); foreach (Property *prop, obj->properties) { int idx = type->metaObject()->indexOfProperty(prop->name.constData()); if (idx == -1) - COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name))); QMetaProperty p = type->metaObject()->property(idx); prop->index = idx; prop->type = p.userType(); if (prop->value || prop->values.count() != 1) - COMPILE_EXCEPTION(prop, tr("Invalid property use")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use")); Value *value = prop->values.at(0); @@ -1719,7 +1720,7 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; if (!isPropertyValue && !isPropertyInterceptor) { - COMPILE_EXCEPTION(prop, tr("Invalid property use")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use")); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); @@ -1777,12 +1778,12 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign object to list")); } } } else { - COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign primitives to lists")); } } @@ -1801,19 +1802,19 @@ bool QmlCompiler::buildListProperty(QmlParser::Property *prop, // at runtime. if (!listTypeIsInterface) { if (!canCoerce(listType, v->object)) { - COMPILE_EXCEPTION(v, tr("Cannot assign object to list")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign object to list")); } } } else if (v->value.isScript()) { if (assignedBinding) - COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Can only assign one binding to lists")); assignedBinding = true; COMPILE_CHECK(buildBinding(v, prop, ctxt)); v->type = Value::PropertyBinding; } else { - COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists")); + COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign primitives to lists")); } } @@ -1941,7 +1942,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, buildDynamicMeta(prop->parent, ForceCreation); v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { - COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property")); + COMPILE_EXCEPTION(v->object, qApp->translate("QmlCompiler","Cannot assign object to property")); } } @@ -1986,12 +1987,12 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) if (prop.isDefaultProperty) { if (seenDefaultProperty) - COMPILE_EXCEPTION(obj, tr("Duplicate default property")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate default property")); seenDefaultProperty = true; } if (propNames.contains(prop.name)) - COMPILE_EXCEPTION(obj, tr("Duplicate property name")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate property name")); propNames.insert(prop.name); } @@ -1999,13 +2000,13 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj) for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) { QByteArray name = obj->dynamicSignals.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, tr("Duplicate signal name")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate signal name")); methodNames.insert(name); } for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) { QByteArray name = obj->dynamicSlots.at(ii).name; if (methodNames.contains(name)) - COMPILE_EXCEPTION(obj, tr("Duplicate method name")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate method name")); methodNames.insert(name); } @@ -2027,7 +2028,7 @@ bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj) property = obj->getProperty(p.name); if (property->value) - COMPILE_EXCEPTION(property, tr("Invalid property nesting")); + COMPILE_EXCEPTION(property, qApp->translate("QmlCompiler","Invalid property nesting")); for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) { Value *v = p.defaultValue->values.at(ii); @@ -2073,7 +2074,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) if (-1 != propIdx) { QMetaProperty prop = obj->metaObject()->property(propIdx); if (prop.isFinal()) - COMPILE_EXCEPTION(&p, tr("Cannot override FINAL property")); + COMPILE_EXCEPTION(&p, qApp->translate("QmlCompiler","Cannot override FINAL property")); } if (p.isDefaultProperty && @@ -2098,7 +2099,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) QmlEnginePrivate *priv = QmlEnginePrivate::get(engine); if (!priv->resolveType(unit->imports, p.customType, &qmltype, &url, 0, 0, 0)) - COMPILE_EXCEPTION(&p, tr("Invalid property type")); + COMPILE_EXCEPTION(&p, qApp->translate("QmlCompiler","Invalid property type")); if (!qmltype) { QmlCompositeTypeData *tdata = priv->typeManager.get(url); @@ -2257,24 +2258,24 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, const Object::DynamicProperty &prop) { if (!prop.defaultValue) - COMPILE_EXCEPTION(obj, tr("No property alias location")); + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","No property alias location")); if (prop.defaultValue->values.count() != 1 || prop.defaultValue->values.at(0)->object || !prop.defaultValue->values.at(0)->value.isScript()) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location")); QmlJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST(); if (!node) - COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen? + COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","No property alias location")); // ### Can this happen? QStringList alias = astNodeToStringList(node); if (alias.count() != 1 && alias.count() != 2) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location")); if (!compileState.ids.contains(alias.at(0))) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location")); Object *idObject = compileState.ids[alias.at(0)]; @@ -2286,7 +2287,7 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); + COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location")); QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); writable = aliasProperty.isWritable(); @@ -2321,7 +2322,7 @@ bool QmlCompiler::buildBinding(QmlParser::Value *value, QMetaProperty mp = prop->parent->metaObject()->property(prop->index); if (!mp.isWritable() && !QmlMetaType::isList(prop->type)) - COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); BindingReference reference; reference.expression = value->value; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 6d6a25e..cff4937 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -135,9 +135,8 @@ private: }; class QMetaObjectBuilder; -class Q_DECLARATIVE_EXPORT QmlCompiler : public QObject +class Q_DECLARATIVE_EXPORT QmlCompiler { - Q_OBJECT public: QmlCompiler(); diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index 75de985..862d6ba 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -75,9 +75,13 @@ QT_BEGIN_NAMESPACE void qmlInfo(const QString& msg, QObject* object) { - QString pos = QLatin1String("QML ") + QLatin1String(object->metaObject()->className()); + QString pos = QLatin1String("QML"); + if (object) { + pos += " "; + pos += QLatin1String(object->metaObject()->className()); + } QmlDeclarativeData *ddata = QmlDeclarativeData::get(object); - pos += QLatin1String("("); + pos += QLatin1String(" ("); if (ddata) { if (ddata->outerContext) { pos += ddata->outerContext->baseUrl().toString(); @@ -91,7 +95,7 @@ void qmlInfo(const QString& msg, QObject* object) } else { pos += qApp->translate("QmlInfo","unknown location"); } - pos += QLatin1String(")"); + pos += QLatin1String(") "); qWarning((pos + msg).toLocal8Bit()); // XXX allow other processing? } diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 675f5ae..1f3903d 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -63,6 +63,7 @@ #include "private/qmlvmemetaobject_p.h" #include #include +#include #include #include #include @@ -75,12 +76,8 @@ QmlVME::QmlVME() #define VME_EXCEPTION(desc) \ { \ - QString str; \ - QDebug d(&str); \ - d << desc; \ - str = str.trimmed(); \ QmlError error; \ - error.setDescription(str); \ + error.setDescription(desc.trimmed()); \ error.setLine(instr.line); \ error.setUrl(comp->url); \ vmeErrors << error; \ @@ -191,7 +188,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if(types.at(instr.create.type).component) vmeErrors << types.at(instr.create.type).component->errors(); - VME_EXCEPTION("Unable to create object of type" << types.at(instr.create.type).className); + VME_EXCEPTION(qApp->translate("QmlVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className))); } QmlDeclarativeData *ddata = QmlDeclarativeData::get(o); @@ -498,7 +495,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QMetaProperty prop = target->metaObject()->property(instr.assignCustomType.propertyIndex); if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) - VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name()); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name()))); void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, @@ -520,15 +517,15 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QMetaMethod method = QmlMetaType::defaultMethod(assign); if (method.signature() == 0) - VME_EXCEPTION("Cannot assign object type" << assign->metaObject()->className() << "with no default method"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className()))); if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) - VME_EXCEPTION("Cannot connect mismatched signal/slot" << method.signature() << prop.method().signature()); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature()))); QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex()); } else { - VME_EXCEPTION("Cannot assign an object to signal property" << pr); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr))); } @@ -684,7 +681,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (iid) ptr = assign->qt_metacast(iid); if (!ptr) - VME_EXCEPTION("Cannot assign object to list"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object to list")); if (list.qmlListInterface) { @@ -730,7 +727,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, } if (!ok) - VME_EXCEPTION("Cannot assign object to interface property"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object to interface property")); } break; @@ -741,7 +738,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); if (!qmlObject) - VME_EXCEPTION("Unable to create attached object"); + VME_EXCEPTION(qApp->translate("QmlVME","Unable to create attached object")); stack.push(qmlObject); } @@ -759,7 +756,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QMetaObject::metacall(target, QMetaObject::ReadProperty, instr.fetchQmlList.property, a); if (!list) - VME_EXCEPTION("Cannot assign to null list"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign to null list")); qliststack.push(ListInstance(list, instr.fetchQmlList.type)); } @@ -777,7 +774,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, QMetaObject::metacall(target, QMetaObject::ReadProperty, instr.fetchQmlList.property, a); if (!list) - VME_EXCEPTION("Cannot assign to null list"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign to null list")); qliststack.push(ListInstance(list, instr.fetchQmlList.type)); } @@ -796,7 +793,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, instr.fetch.property, a); if (!obj) - VME_EXCEPTION("Cannot set properties on" << target->metaObject()->property(instr.fetch.property).name() << "as it is null"); + VME_EXCEPTION(qApp->translate("QmlVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name()))); stack.push(obj); } diff --git a/tests/auto/declarative/anchors/tst_anchors.cpp b/tests/auto/declarative/anchors/tst_anchors.cpp index 38b7fe8..ec977da 100644 --- a/tests/auto/declarative/anchors/tst_anchors.cpp +++ b/tests/auto/declarative/anchors/tst_anchors.cpp @@ -102,7 +102,7 @@ void tst_anchors::loops() view->setUrl(QUrl("file://" SRCDIR "/data/loop1.qml")); - QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Possible anchor loop detected on horizontal anchor. "; + QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Possible anchor loop detected on horizontal anchor."; QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); @@ -117,7 +117,7 @@ void tst_anchors::loops() view->setUrl(QUrl("file://" SRCDIR "/data/loop2.qml")); - QString expect = "QML QFxImage (" + view->url().toString() + ":14:3" + ") Possible anchor loop detected on horizontal anchor. "; + QString expect = "QML QFxImage (" + view->url().toString() + ":14:3" + ") Possible anchor loop detected on horizontal anchor."; QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); qApp->processEvents(); @@ -133,7 +133,7 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal1.qml")); - QString expect = "QML QFxRect (" + view->url().toString() + ":7:5" + ") Can't specify left, right, and hcenter anchors. "; + QString expect = "QML QFxRect (" + view->url().toString() + ":7:5" + ") Can't specify left, right, and hcenter anchors."; QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); qApp->processEvents(); @@ -146,7 +146,7 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal2.qml")); - QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors. "; + QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors."; QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); //qApp->processEvents(); @@ -159,7 +159,7 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal3.qml")); - QString expect = "QML QFxRect (" + view->url().toString() + ":9:5" + ") Can't anchor to an item that isn't a parent or sibling. "; + QString expect = "QML QFxRect (" + view->url().toString() + ":9:5" + ") Can't anchor to an item that isn't a parent or sibling."; QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); //qApp->processEvents(); @@ -187,7 +187,7 @@ void tst_anchors::nullItem() { QFxAnchorLine anchor; - QTest::ignoreMessage(QtWarningMsg, "QML QFxItem (unknown location): Can't anchor to a null item. "); + QTest::ignoreMessage(QtWarningMsg, "QML QFxItem (unknown location) Can't anchor to a null item."); QFxItem *item = new QFxItem; item->anchors()->setBottom(anchor); } diff --git a/tests/auto/declarative/animations/tst_animations.cpp b/tests/auto/declarative/animations/tst_animations.cpp index f627527..0e46224 100644 --- a/tests/auto/declarative/animations/tst_animations.cpp +++ b/tests/auto/declarative/animations/tst_animations.cpp @@ -152,7 +152,7 @@ void tst_animations::badProperties() QFxRect *rect = qobject_cast(c.create()); QVERIFY(rect); - QTest::ignoreMessage(QtWarningMsg, "QML QmlColorAnimation (file://" SRCDIR "/data/badproperty1.qml:22:9) Cannot animate non-existant property \"pen.colr\" "); + QTest::ignoreMessage(QtWarningMsg, "QML QmlColorAnimation (file://" SRCDIR "/data/badproperty1.qml:22:9) Cannot animate non-existant property \"pen.colr\""); rect->setState("state1"); } } diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index f976e41..7fb1703 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -154,7 +154,7 @@ void tst_qmlecmascript::methods() void tst_qmlecmascript::bindingLoop() { QmlComponent component(&engine, TEST_FILE("bindingLoop.qml")); - QString warning = "QML MyQmlObject (" + component.url().toString() + ":9:9) Binding loop detected for property \"stringProperty\" "; + QString warning = "QML MyQmlObject (" + component.url().toString() + ":9:9) Binding loop detected for property \"stringProperty\""; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); QObject *object = component.create(); QVERIFY(object != 0); -- cgit v0.12 From 3fd624b77669fb503d2762926c3153596cfb284b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 11:42:07 +1000 Subject: Doc --- .../flickr/mobile/images/toolbutton.png | Bin 2619 -> 2550 bytes doc/src/declarative/anatomy.qdoc | 74 -------- doc/src/declarative/pics/anatomy-component.png | Bin 0 -> 16117 bytes doc/src/declarative/qmldocument.qdoc | 188 +++++++++++++++++++++ doc/src/declarative/qtdeclarative.qdoc | 2 +- 5 files changed, 189 insertions(+), 75 deletions(-) delete mode 100644 doc/src/declarative/anatomy.qdoc create mode 100644 doc/src/declarative/pics/anatomy-component.png create mode 100644 doc/src/declarative/qmldocument.qdoc diff --git a/demos/declarative/flickr/mobile/images/toolbutton.png b/demos/declarative/flickr/mobile/images/toolbutton.png index 8862898..1131001 100644 Binary files a/demos/declarative/flickr/mobile/images/toolbutton.png and b/demos/declarative/flickr/mobile/images/toolbutton.png differ diff --git a/doc/src/declarative/anatomy.qdoc b/doc/src/declarative/anatomy.qdoc deleted file mode 100644 index f816464..0000000 --- a/doc/src/declarative/anatomy.qdoc +++ /dev/null @@ -1,74 +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 documentation 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$ -** -****************************************************************************/ - -/*! -\page qmldocumentanatomy.html -\title Anatomy of a QML Document - -A QML document is a block of QML source code. QML documents generally correspond to files -stored on a disk or network resource, but can be constructed directly from text data. - -Syntactically a QML document is self contained; QML does \e not have a preprocessor that -modifies the document prior to presentation to the QML runtime. Type references made within -a QML document, including within a \l {ECMAScript Block} contained by the document, are -resolved based exclusively on the import statements present in the document. - -A simple QML document looks like this: - -\code -import Qt 4.6 - -Rectangle { - Component { - id: contactDelegate - Text { - text: modelData.firstName + " " + modelData.lastName - } - } - - ListView { - model: contactModel - delegate: contactDelegate - } -} -\endcode - -*/ diff --git a/doc/src/declarative/pics/anatomy-component.png b/doc/src/declarative/pics/anatomy-component.png new file mode 100644 index 0000000..70ed983 Binary files /dev/null and b/doc/src/declarative/pics/anatomy-component.png differ diff --git a/doc/src/declarative/qmldocument.qdoc b/doc/src/declarative/qmldocument.qdoc new file mode 100644 index 0000000..84e7926 --- /dev/null +++ b/doc/src/declarative/qmldocument.qdoc @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +/*! +\page qmldocuments.html +\title QML Documents + +A QML document is a block of QML source code. QML documents generally correspond to files +stored on a disk or network resource, but can be constructed directly from text data. + +A simple QML document looks like this: + +\code +import Qt 4.6 + +Rectangle { + width: 240; height: 320; + + resources: [ + Component { + id: contactDelegate + Text { + text: modelData.firstName + " " + modelData.lastName + } + } + ] + + ListView { + anchors.fill: parent + model: contactModel + delegate: contactDelegate + } +} +\endcode + +A QML document always begins with one or more import statements. To prevent elements +introduced in later versions from affecting existing QML programs, the element types +available within a document are controlled by the imported QML \l {Modules}. That is, +QML is a \e versioned language. + +Syntactically a QML document is self contained; QML does \e not have a preprocessor that +modifies the document prior to presentation to the QML runtime. \c import statements +do not "include" code in the document, but instead instruct the QML runtime on how to +resolve type references found in the document. Any type reference present in a QML +document - such as \c Rectangle and \c ListView - including those made within an +\l {ECMAScript Block} or \l {Property Binding}s, are \e resolved based exclusively on the +import statements. QML does not import any modules by default, so at least one \c import +statement must be present or no elements will be available! + +A QML document defines a single, top-level \l {QmlComponent}{QML component}. A QML component +is a template that is interpreted by the QML runtime to create an object with some predefined +behaviour. As it is a template, a single QML component can be "run" multiple times to +produce several objects, each of which are said to be \e instances of the component. + +Once created, instances are not dependent on the component that created them, so they can +operate on independent data. Here is an example of a simple "button" component that is +instantiated four times, each with a different value for its \c text property. + +\table +\row +\o +\raw HTML +
+\endraw +\code +import Qt 4.6 + +BorderImage { + property alias text: textElement.text + width: 100; height: 30; source: "images/toolbutton.sci" + + Text { + id: textElement + anchors.centerIn: parent + font.pointSize: 20 + style: Text.Raised + color: "white" + } +} +\endcode +\raw HTML + +\endraw +\image anatomy-component.png +\raw HTML +
+\endraw +\endtable + +In addition to the top-level component that all QML documents define, documents may also +include additional \e inline components. Inline components are declared using the +\l Component element, as can be seen in the first example above. Inline components share +all the characteristics of regular top-level components and use the same \c import list as their +containing QML document. Components are one of the most basic building blocks in QML, and are +frequently used as "factories" by other elements. For example, the \l ListView element uses the +\c delegate component as the template for instantiating list items - each list item is just a +new instance of the component with the item specific data set appropriately. + +Like other \l {QML Elements}, the \l Component element is an object and must be assigned to a +property. \l Component objects may also have an object id. In the first example on this page, +the inline component is added to the \l Rectangle's \c resources list, and then +\l {Property Binding} is used to assign the \l Component to the \l ListView's \c delegate +property. While using property binding allows the \l Component object to be shared (for example, +if the QML document contained multiple \l ListView's with the same delegate), in this case the +\l Component could have been assigned directly to the \l ListView's \c delegate. The QML +language even contains a syntactic optimization when assigning directly to a component property +for this case where it will automatically insert the \l Component tag. + +These final two examples are behaviorally identical to the original document. + +\table +\row +\o +\code +import Qt 4.6 + +Rectangle { + width: 240; height: 320; + + ListView { + anchors.fill: parent + model: contactModel + delegate: Component { + Text { + text: modelData.firstName + " " + modelData.lastName + } + } + } +} +\endcode +\o +\code +import Qt 4.6 + +Rectangle { + width: 240; height: 320; + + ListView { + anchors.fill: parent + model: contactModel + delegate: Text { + text: modelData.firstName + " " + modelData.lastName + } + } +} +\endcode +\endtable + +\sa QmlComponent +*/ diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index 56f3252..bd50034 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -81,7 +81,7 @@ completely new applications. QML is fully \l {Extending QML}{extensible from C+ \section1 Core QML Features: \list -\o \l {Anatomy of a QML Document} +\o \l {QML Documents} \o \l {Property Binding} \o \l {ECMAScript Blocks} \o \l {Network Transparency} -- cgit v0.12 From 2c36d7c63fc88b1f06582884fd3ea0b26534a2cd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 13:55:55 +1000 Subject: Don't pass a pointer to invalid memory --- src/declarative/qml/qmltypenamescriptclass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index c0613d1..7a14432 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -115,11 +115,11 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, // Must be an enum if (data->mode == IncludeEnums) { // ### Optimize - const char *enumName = strName.toUtf8().constData(); + QByteArray enumName = strName.toUtf8(); const QMetaObject *metaObject = data->type->baseMetaObject(); for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName); + int value = e.keyToValue(enumName.constData()); if (value != -1) { enumValue = value; return QScriptClass::HandlesReadAccess; -- cgit v0.12 From 6762b13d07d759d150a87efa9b2724d7f8955f62 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 14:12:08 +1000 Subject: Doc --- doc/src/declarative/tutorial.qdoc | 6 +++--- doc/src/declarative/tutorial1.qdoc | 3 +-- doc/src/declarative/tutorial2.qdoc | 3 +-- doc/src/declarative/tutorial3.qdoc | 3 +-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/doc/src/declarative/tutorial.qdoc b/doc/src/declarative/tutorial.qdoc index b59384c..19921c0 100644 --- a/doc/src/declarative/tutorial.qdoc +++ b/doc/src/declarative/tutorial.qdoc @@ -15,9 +15,9 @@ The tutorial's source code is located in the $QTDIR/examples/declarative/tutoria Tutorial chapters: \list -\o \l {tutorial1}{Tutorial 1 - Basic Types} -\o \l {tutorial2}{Tutorial 2 - QML Component} -\o \l {tutorial3}{Tutorial 3 - States and Transitions} +\o \l {Tutorial 1 - Basic Types} +\o \l {Tutorial 2 - QML Component} +\o \l {Tutorial 3 - States and Transitions} \endlist */ diff --git a/doc/src/declarative/tutorial1.qdoc b/doc/src/declarative/tutorial1.qdoc index ad454f2..f7e44b0 100644 --- a/doc/src/declarative/tutorial1.qdoc +++ b/doc/src/declarative/tutorial1.qdoc @@ -1,6 +1,5 @@ /*! \page tutorial1.html -\target tutorial1 \title Tutorial 1 - Basic Types This first program is a very simple "Hello world" example that introduces some basic QML concepts. @@ -52,6 +51,6 @@ For example, to run the provided completed Tutorial 1 example from the install l bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/tutorial1.qml \endcode -[\l tutorial] [Next: \l tutorial2] +[\l {Tutorial}] [Next: \l {Tutorial 2 - QML Component}] */ diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc index 796d0f9..ac63d9b 100644 --- a/doc/src/declarative/tutorial2.qdoc +++ b/doc/src/declarative/tutorial2.qdoc @@ -1,6 +1,5 @@ /*! \page tutorial2.html -\target tutorial2 \title Tutorial 2 - QML Component This chapter adds a color picker to change the color of the text. @@ -65,7 +64,7 @@ We create the color picker by putting 6 cells with different colors in a grid. When the \e clicked signal of our cell is triggered, we want to set the color of the text to the color passed as a parameter. We can react to any signal of our component through a property of the name \e 'onSignalName' (see \l{Signal Handlers}). -[Previous: \l tutorial1] [Next: \l tutorial3] +[Previous: \l {Tutorial 1 - Basic Types}] [Next: \l {Tutorial 3 - States and Transitions}] */ diff --git a/doc/src/declarative/tutorial3.qdoc b/doc/src/declarative/tutorial3.qdoc index 8ef32d4..1e67eee 100644 --- a/doc/src/declarative/tutorial3.qdoc +++ b/doc/src/declarative/tutorial3.qdoc @@ -1,6 +1,5 @@ /*! \page tutorial3.html -\target tutorial3 \title Tutorial 3 - States and Transitions In this chapter, we make this example a little bit more dynamic by introducing states and transitions. @@ -41,6 +40,6 @@ We could also run them one after the other by using \l SequentialAnimation inste For more details on states and transitions, see \l {states-transitions}{States and Transitions}. -[Previous: \l tutorial2] [\l tutorial] +[Previous: \l {Tutorial 2 - QML Component}] [\l {Tutorial}] */ -- cgit v0.12 From f15ef2bdbf3698669dd4d2acf83b2608b7a6bc7c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 14:19:32 +1000 Subject: Doc --- doc/src/declarative/qtdeclarative.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index bd50034..1581e3d 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -62,7 +62,7 @@ existing QObject based type system, adds support for automatic level. The \l {QML Elements} are a sophisticated set of graphical and behavioral building -blocks. \l {QML Elements} are combined together in QML files to build components +blocks. \l {QML Elements} are combined together in \l {QML Documents} to build components ranging in complexity from simple pushbuttons and sliders, to complete internet-enabled applications like a \l {http://www.flickr.com}{flickr} photo browser. -- cgit v0.12 From 423ccd84379a6d8af647f76ed4bddac767230f17 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 13 Oct 2009 15:22:05 +1000 Subject: Library importing requires a version. Fix and test. --- src/declarative/qml/qmlscriptparser.cpp | 12 ++++++++++-- .../qmllanguage/data/importVersionMissingBuiltIn.errors.txt | 2 +- .../data/importVersionMissingInstalled.errors.txt | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 57e40b6..c45bdcc 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -294,7 +294,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, if (isScript) { if (_stateStack.isEmpty() || _stateStack.top().property) { QmlError error; - error.setDescription(QLatin1String("Invalid use of Script block")); + error.setDescription(QCoreApplication::translate("QmlParser","Invalid use of Script block")); error.setLine(typeLocation.startLine); error.setColumn(typeLocation.startColumn); _parser->_errors << error; @@ -474,7 +474,7 @@ bool ProcessAST::visit(AST::UiImport *node) import.qualifier = node->importId->asString(); if (!import.qualifier.at(0).isUpper()) { QmlError error; - error.setDescription(QLatin1String("Invalid import qualifier ID")); + error.setDescription(QCoreApplication::translate("QmlParser","Invalid import qualifier ID")); error.setLine(node->importIdToken.startLine); error.setColumn(node->importIdToken.startColumn); _parser->_errors << error; @@ -483,6 +483,14 @@ bool ProcessAST::visit(AST::UiImport *node) } if (node->versionToken.isValid()) import.version = textAt(node->versionToken); + else if (import.type == QmlScriptParser::Import::Library) { + QmlError error; + error.setDescription(QCoreApplication::translate("QmlParser","Library import requires a version")); + error.setLine(node->importIdToken.startLine); + error.setColumn(node->importIdToken.startColumn); + _parser->_errors << error; + return false; + } import.location = location(startLoc, endLoc); import.uri = uri; diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt index 2235cbc..c7d880e 100644 --- a/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt +++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingBuiltIn.errors.txt @@ -1 +1 @@ -SHOULD GIVE AN ERROR ABOUT MISSING VERSION +1:16:Library import requires a version diff --git a/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt index 2235cbc..89e58ee 100644 --- a/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt +++ b/tests/auto/declarative/qmllanguage/data/importVersionMissingInstalled.errors.txt @@ -1 +1 @@ -SHOULD GIVE AN ERROR ABOUT MISSING VERSION +1:35:Library import requires a version -- cgit v0.12 From 278b97494dbeed4be391caf32537fd19f19f0186 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 13 Oct 2009 15:34:14 +1000 Subject: Stop crash (stop on error) --- src/declarative/qml/qmlscriptparser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index c45bdcc..9cc12b3 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -298,6 +298,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, error.setLine(typeLocation.startLine); error.setColumn(typeLocation.startColumn); _parser->_errors << error; + return 0; } } -- cgit v0.12 From 5339cd51fa4235b87a41135b8a7d8bcc671a0e88 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 15:45:37 +1000 Subject: Doc --- doc/src/declarative/examples.qdoc | 51 ++++++++++++++++++++++++---- doc/src/declarative/pics/dial-example.gif | Bin 0 -> 566465 bytes doc/src/declarative/pics/switch-example.gif | Bin 0 -> 25270 bytes doc/src/declarative/qtdeclarative.qdoc | 4 +-- 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 doc/src/declarative/pics/dial-example.gif create mode 100644 doc/src/declarative/pics/switch-example.gif diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc index 7a03685..9d66089 100644 --- a/doc/src/declarative/examples.qdoc +++ b/doc/src/declarative/examples.qdoc @@ -41,7 +41,9 @@ /*! \page qmlexamples.html -\title QML Examples +\title QML Examples and Walkthroughs + +\section1 Running Examples A \l {qmlviewer}{viewer} application is included that allows you to quickly explore many of the examples. It has some useful options, revealed by: @@ -63,12 +65,47 @@ or Many other simple examples can be found under the \c examples/declarative sub directory. Some can be run directly using the viewer like those above, and -others require you to build and run an executable. +others require you to build and run an executable. More sophisticated demos of +large applications can be found under the \c demos/declarative sub directory. +These are intended to show more integrated functionality rather than to be +instructive on specific elements. + +\section1 Examples + +These will be documented, and demonstrate how to achieve various things in QML. -More sophisticated demos of large applications can be found under the \c demos/declarative -sub directory. These are intended to show more integrated functionality rather than -to be instructive on specific elements. +\raw HTML +
+ + + + + + + + + + +
+\endraw +\image dial-example.gif +\raw HTML + +\endraw +\image switch-example.gif +\raw HTML + +\endraw +\image declarative-adv-tutorial4.gif +\raw HTML +
+
Elastic Dial
+
+
Touch Toggle Switch
+
+
Samegame
+
+
+\endraw -Finally, check out the \l {tutorial} to learn a little more about writing your -own QML-based applications. */ diff --git a/doc/src/declarative/pics/dial-example.gif b/doc/src/declarative/pics/dial-example.gif new file mode 100644 index 0000000..4e90ba9 Binary files /dev/null and b/doc/src/declarative/pics/dial-example.gif differ diff --git a/doc/src/declarative/pics/switch-example.gif b/doc/src/declarative/pics/switch-example.gif new file mode 100644 index 0000000..3d6582f Binary files /dev/null and b/doc/src/declarative/pics/switch-example.gif differ diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index 1581e3d..73814db 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -73,10 +73,10 @@ completely new applications. QML is fully \l {Extending QML}{extensible from C+ \section1 Getting Started: \list \o \l {Introduction to the QML language} -\o \l {tutorial}{Tutorial: 'Hello World'} +\o \l {Tutorial}{Tutorial: 'Hello World'} \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} -\o \l {QML Examples} +\o \l {QML Examples and Walkthroughs} \endlist \section1 Core QML Features: -- cgit v0.12 From c8198d40af104b5555a975b3156e9d5ba1981e25 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 13 Oct 2009 17:00:21 +1000 Subject: Doc --- doc/src/declarative/ecmascriptblocks.qdoc | 126 +++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 9 deletions(-) diff --git a/doc/src/declarative/ecmascriptblocks.qdoc b/doc/src/declarative/ecmascriptblocks.qdoc index 4dde19d..f683af8 100644 --- a/doc/src/declarative/ecmascriptblocks.qdoc +++ b/doc/src/declarative/ecmascriptblocks.qdoc @@ -43,17 +43,21 @@ \page qmlecmascript.html \title ECMAScript Blocks -QML encourages building UIs declaratively, using \l {Property Binding} and existing -\l {QML Elements}. When imperative code is required to implementing more advanced -behavior, the \l Script element can be used to add ECMAScript code directly to a -QML file, or to include an external ECMAScript file. +QML encourages building UIs declaratively, using \l {Property Binding} and the +composition of existing \l {QML Elements}. If imperative code is required to implement +more advanced behavior, the \l Script element can be used to add ECMAScript code directly +to a QML file, or to include an external ECMAScript file. The \l Script element is a QML language \e intrinsic. It can be used anywhere in a -QML file. \e except as the root element of a file or sub-component. The included -ECMAScript is evaluated in a scope chain. The \l {QML Scope} documentation covers -the specifics of scoping in QML. +QML file, \e except as the root element of a file or sub-component, but cannot be +assigned to an object property or given an id. The included ECMAScript is evaluated +in a scope chain. The \l {QML Scope} documentation covers the specifics of scoping +in QML. -\section1 Inline ECMAScript +\section1 Inline Script + +Small blocks of ECMAScript can be included directly inside a \l {QML Document} as +the body of the \l Script element. \code Rectangle { @@ -69,6 +73,110 @@ Rectangle { } \endcode -\section1 Including a ECMAScript File +Good programming practice dictates that only small script snippets should be written +inline. QML prohibits the declaration of anything other than functions in an inline +script block. For example, the following script is illegal as an inline script block +as it declares the non-function variable \c lastResult. + +\code +// Illegal inline code block +var lastResult = 0 +function factorial(var a) { + a = Integer(a); + if (a <= 0) + lastResult = 1; + else + lastResult = a * factorial(a - 1); + return lastResult; +} +\endcode + +\section1 Including an External File + +To avoid cluttering the QML file, large script blocks should be in a separate file. +The \l Script element's \c source property is used to load script from an external +file. + +If the previous factorial code that was illegal as an inline script block was saved +into a "factorial.js" file, it could be included like this. + +\code +Rectangle { + Script { + source: "factorial.js" + } +} +\endcode + +The \c source property may reference a relative file, or an absolute path. In the +case of a relative file, the location is resolved relative to the location of the +\l {QML Document} that contains the \l Script element. If the script file is not +accessible, an error will occur. If the source is on a network resource, the +enclosing QML document will remain in the \l {QmlComponent::status()}{waiting state} +until the script has been retrieved. + +\section1 QML Script Restrictions + +QML \l Script blocks contain standard ECMAScript code. QML introduces the following +restrictions. + +\list +\o Script code cannot modify the global object. + +In QML, the global object is constant - existing properties cannot be modified or +deleted, and no new properties may be created. + +Most ECMAScript programs do not explicitly modify the global object. However, +ECMAScript's automatic creation of undeclared variables is an implicit modification +of the global object, and is prohibited in QML. + +Assuming that the \c a variable does not exist in the scope chain, the following code +is illegal in QML. + +\code +// Illegal modification of undeclared variable +a = 1; +for (var ii = 1; ii < 10; ++ii) a = a * ii; +print("Result: " + a); +\endcode + +It can be trivially modified to this legal code. + +\code +var a = 1; +for (var ii = 1; ii < 10; ++ii) a = a * ii; +print("Result: " + a); +\endcode + +Any attempt to modify the global object - either implicitly or explicitly - will +cause an exception. If uncaught, this will result in an warning being printed, +that includes the file and line number of the offending code. + +\o Global code is run in a reduced scope + +During startup, if a \l Script block includes an external file with "global" +code, it is executed in a scope that contains only the external file itself and +the global object. That is, it will not have access to the QML objects and +properties it \l {QML Scope}{normally would}. + +Global code that only accesses script local variable is permitted. This is an +example of valid global code. + +\code +var colors = [ "red", "blue", "green", "orange", "purple" ]; +\endcode + +Global code that accesses QML objects will not run correctly. + +\code +// Invalid global code - the "rootObject" variable is undefined +var initialPosition = { rootObject.x, rootObject.y } +\endcode + +This restriction exists as the QML environment is not yet fully established. +To run code after the environment setup has completed - at "startup" - use +the \l Component \c onCompleted attached property. + +\endlist */ -- cgit v0.12 From 3491cdb2c1c9184adfb0fab1e636afd784a6565e Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 14 Oct 2009 09:17:53 +1000 Subject: fix test (data now shadowed, Script changed) --- tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp index c9c37ab..c1b31c2 100644 --- a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp +++ b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include class tst_QBindableMap : public QObject @@ -58,11 +59,13 @@ void tst_QBindableMap::changed() //make changes in QML QmlEngine engine; QmlContext *ctxt = engine.rootContext(); - ctxt->setContextProperty(QLatin1String("data"), &map); - QmlComponent component(&engine, "import Qt 4.6\nScript { script: \"data.key1 = 'Hello World';\" }", + ctxt->setContextProperty(QLatin1String("testdata"), &map); + QmlComponent component(&engine, "import Qt 4.6\nText { text: { testdata.key1 = 'Hello World'; 'X' } }", QUrl("file://")); QVERIFY(component.isReady()); - component.create(); + QFxText *txt = qobject_cast(component.create()); + QVERIFY(txt); + QCOMPARE(txt->text(), QString('X')); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toString(),QLatin1String("key1")); -- cgit v0.12 From 0a10af2463d73106c2f1268553aa6e60890f6180 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 14 Oct 2009 11:32:03 +1000 Subject: Add Component::onCompleted attached property --- doc/src/declarative/ecmascriptblocks.qdoc | 35 +++++++++++- src/declarative/qml/qmlcomponent.cpp | 65 ++++++++++++++++++++++ src/declarative/qml/qmlcomponent.h | 3 + src/declarative/qml/qmlcomponent_p.h | 21 ++++++- src/declarative/qml/qmlengine.cpp | 4 +- src/declarative/qml/qmlengine_p.h | 2 + .../qmllanguage/data/OnCompletedType.qml | 8 +++ .../declarative/qmllanguage/data/onCompleted.qml | 17 ++++++ .../declarative/qmllanguage/tst_qmllanguage.cpp | 13 +++++ 9 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/OnCompletedType.qml create mode 100644 tests/auto/declarative/qmllanguage/data/onCompleted.qml diff --git a/doc/src/declarative/ecmascriptblocks.qdoc b/doc/src/declarative/ecmascriptblocks.qdoc index f683af8..815c68c 100644 --- a/doc/src/declarative/ecmascriptblocks.qdoc +++ b/doc/src/declarative/ecmascriptblocks.qdoc @@ -115,6 +115,37 @@ accessible, an error will occur. If the source is on a network resource, the enclosing QML document will remain in the \l {QmlComponent::status()}{waiting state} until the script has been retrieved. +\section1 Running Script at Startup + +It is occasionally necessary to run a block of ECMAScript code at application (or +component instance) "startup". While it is tempting to just include the startup +script as \e {global code} in an external script file, this can have sever limitations +as the QML environment may not have been fully established. For example, some objects +might not have been created or some \l {Property Binding}s may not have been run. +\l {QML Script Restrictions} covers the exact limitations of global script code. + +The QML \l Component element provides an \e attached \c onCompleted property that +can be used to trigger the execution of script code at startup after the +QML environment has been completely established. + +The following QML code shows how to use the \c Component::onCompleted property. + +\code +Rectangle { + Script { + function startupFunction() { + // ... startup code + } + } + + Component.onCompleted: startupFunction(); +} +\endcode + +Any element in a QML file - including nested elements and nested QML component +instances - can use this attached property. If there is more than one script to +execute at startup, they are run sequentially in an undefined order. + \section1 QML Script Restrictions QML \l Script blocks contain standard ECMAScript code. QML introduces the following @@ -174,8 +205,8 @@ var initialPosition = { rootObject.x, rootObject.y } \endcode This restriction exists as the QML environment is not yet fully established. -To run code after the environment setup has completed - at "startup" - use -the \l Component \c onCompleted attached property. +To run code after the environment setup has completed, refer to +\l {Running Script at Startup}. \endlist diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 9a761b2..dc71989 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -95,6 +95,27 @@ Item { Loader { sourceComponent: RedSquare; x: 20 } } \endqml + + \section1 Attached Properties + + \e onCompleted + + Emitted after component "startup" has completed. This can be used to + execute script code at startup, once the full QML environment has been + established. + + The \c {Component::onCompleted} attached property can be applied to + any element. The order of running the \c onCompleted scripts is + undefined. + + \qml + Rectangle { + Component.onCompleted: print("Completed Running!") + Rectangle { + Component.onCompleted: print("Nested Completed Running!") + } + } + \endqml */ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Component,QmlComponent); @@ -532,6 +553,11 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings) bindValues = ep->bindValues; parserStatus = ep->parserStatus; + componentAttacheds = ep->componentAttacheds; + if (componentAttacheds) + componentAttacheds->prev = &componentAttacheds; + + ep->componentAttacheds = 0; ep->bindValues.clear(); ep->parserStatus.clear(); completePending = true; @@ -593,10 +619,49 @@ void QmlComponentPrivate::completeCreate() QmlEnginePrivate::clear(ps); } + while (componentAttacheds) { + QmlComponentAttached *a = componentAttacheds; + if (a->next) a->next->prev = &componentAttacheds; + componentAttacheds = a->next; + a->prev = 0; a->next = 0; + emit a->completed(); + } + bindValues.clear(); parserStatus.clear(); completePending = false; } } +QmlComponentAttached::QmlComponentAttached(QObject *parent) +: QObject(parent), prev(0), next(0) +{ +} + +QmlComponentAttached::~QmlComponentAttached() +{ + if (prev) *prev = next; + if (next) next->prev = prev; + prev = 0; + next = 0; +} + +QmlComponentAttached *QmlComponent::qmlAttachedProperties(QObject *obj) +{ + QmlComponentAttached *a = new QmlComponentAttached(obj); + + QmlEngine *engine = qmlEngine(obj); + if (!engine || !QmlEnginePrivate::get(engine)->rootComponent) + return a; + + QmlEnginePrivate *p = QmlEnginePrivate::get(engine); + + a->next = p->componentAttacheds; + a->prev = &p->componentAttacheds; + if (a->next) a->next->prev = &a->next; + p->componentAttacheds = a; + + return a; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h index c6924e3..dcf9347 100644 --- a/src/declarative/qml/qmlcomponent.h +++ b/src/declarative/qml/qmlcomponent.h @@ -59,6 +59,7 @@ class QmlCompiledData; class QByteArray; class QmlComponentPrivate; class QmlEngine; +class QmlComponentAttached; class Q_DECLARATIVE_EXPORT QmlComponent : public QObject { Q_OBJECT @@ -95,6 +96,8 @@ public: void loadUrl(const QUrl &url); void setData(const QByteArray &, const QUrl &baseUrl); + static QmlComponentAttached *qmlAttachedProperties(QObject *); + Q_SIGNALS: void statusChanged(QmlComponent::Status); void progressChanged(qreal); diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index 2d0c77f..7eedfbd 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -70,12 +70,13 @@ class QmlComponent; class QmlEngine; class QmlCompiledData; +class QmlComponentAttached; class QmlComponentPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QmlComponent) public: - QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), completePending(false), engine(0) {} + QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), completePending(false), componentAttacheds(0), engine(0) {} QObject *create(QmlContext *context, const QBitField &); @@ -98,6 +99,7 @@ public: QList > bindValues; QList > parserStatus; + QmlComponentAttached *componentAttacheds; bool completePending; @@ -110,6 +112,23 @@ public: } }; +class QmlComponentAttached : public QObject +{ + Q_OBJECT +public: + QmlComponentAttached(QObject *parent = 0); + ~QmlComponentAttached(); + + QmlComponentAttached **prev; + QmlComponentAttached *next; + +signals: + void completed(); + +private: + friend class QmlComponentPrivate; +}; + QT_END_NAMESPACE #endif // QMLCOMPONENT_P_H diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ef0f975..7e95428 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -125,8 +125,8 @@ static QString userLocalDataPath(const QString& app) QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) : rootContext(0), currentExpression(0), isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0), - nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), scriptEngine(this), rootComponent(0), - networkAccessManager(0), typeManager(e), uniqueId(1) + nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), scriptEngine(this), + componentAttacheds(0), rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1) { QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get()); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 7978023..4c90a80 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -95,6 +95,7 @@ class QmlAbstractBinding; class QScriptDeclarativeClass; class QmlTypeNameScriptClass; class QmlTypeNameCache; +class QmlComponentAttached; class QmlEnginePrivate : public QObjectPrivate { @@ -174,6 +175,7 @@ public: QList > bindValues; QList > parserStatus; + QmlComponentAttached *componentAttacheds; QmlComponent *rootComponent; mutable QNetworkAccessManager *networkAccessManager; diff --git a/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml b/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml new file mode 100644 index 0000000..cdba495 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/OnCompletedType.qml @@ -0,0 +1,8 @@ +import Test 1.0 +import Qt 4.6 + +MyQmlObject { + property int a: Math.max(10, 9) + property int b: 11 + Component.onCompleted: print("Completed " + a + " " + b); +} diff --git a/tests/auto/declarative/qmllanguage/data/onCompleted.qml b/tests/auto/declarative/qmllanguage/data/onCompleted.qml new file mode 100644 index 0000000..ae47d4b --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/onCompleted.qml @@ -0,0 +1,17 @@ +import Test 1.0 +import Qt 4.6 + +MyTypeObject { + // We set a and b to ensure that onCompleted is executed after bindings and + // constants have been assigned + property int a: Math.min(6, 7) + Component.onCompleted: print("Completed " + a + " " + nestedObject.b) + + objectProperty: OnCompletedType { + qmlobjectProperty: MyQmlObject { + id: nestedObject + property int b: 10 + Component.onCompleted: print("Completed " + a + " " + nestedObject.b) + } + } +} diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index cf42792..b99d040 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -60,6 +60,7 @@ private slots: void componentCompositeType(); void i18n(); void i18n_data(); + void onCompleted(); void importsBuiltin_data(); void importsBuiltin(); @@ -705,6 +706,18 @@ void tst_qmllanguage::i18n() delete object; } +// Check that the Component::onCompleted attached property works +void tst_qmllanguage::onCompleted() +{ + QmlComponent component(&engine, TEST_FILE("onCompleted.qml")); + VERIFY_ERRORS(0); + QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Completed 6 10"); + QTest::ignoreMessage(QtDebugMsg, "Completed 10 11"); + QObject *object = component.create(); + QVERIFY(object != 0); +} + // Check that first child of qml is of given type. Empty type insists on error. void tst_qmllanguage::testType(const QString& qml, const QString& type) { -- cgit v0.12 From cca9125431672193e93676ebd449c48664b52ba3 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 14 Oct 2009 13:05:06 +1000 Subject: Fix animation autotests. --- tests/auto/declarative/animations/data/badproperty1.qml | 2 +- tests/auto/declarative/animations/tst_animations.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/animations/data/badproperty1.qml b/tests/auto/declarative/animations/data/badproperty1.qml index a01753e..78da34a 100644 --- a/tests/auto/declarative/animations/data/badproperty1.qml +++ b/tests/auto/declarative/animations/data/badproperty1.qml @@ -16,7 +16,7 @@ Rectangle { } states: State { name: "state1" - PropertyChanges { target: MyRect; pen.color: "blue" } + PropertyChanges { target: MyRect; border.color: "blue" } } transitions: Transition { ColorAnimation { target: MyRect; to: "red"; properties: "pen.colr"; duration: 1000 } diff --git a/tests/auto/declarative/animations/tst_animations.cpp b/tests/auto/declarative/animations/tst_animations.cpp index 0e46224..336f0d3 100644 --- a/tests/auto/declarative/animations/tst_animations.cpp +++ b/tests/auto/declarative/animations/tst_animations.cpp @@ -86,7 +86,7 @@ void tst_animations::dotProperty() QTest::qWait(animation.duration() + 50); QCOMPARE(rect.border()->width(), 10); - rect.border()->setWidth(1); + rect.border()->setWidth(0); animation.start(); animation.pause(); animation.setCurrentTime(125); -- cgit v0.12 From 403350d5d6d85fb1ef9718401a6a60af313eaf5a Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 14 Oct 2009 13:09:38 +1000 Subject: Workaround QUrl::toLocalFile not knowing about qrc: QNetworkAccess does similar things. --- src/declarative/extra/qmlfontloader.cpp | 14 ++++++++++++-- src/declarative/fx/qfxborderimage.cpp | 14 ++++++++++++-- src/declarative/fx/qfxpixmapcache.cpp | 18 ++++++++++++++---- src/declarative/qml/qmlcompositetypemanager.cpp | 18 ++++++++++++++---- src/declarative/qml/qmlengine.cpp | 13 +++++++++++-- 5 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/declarative/extra/qmlfontloader.cpp b/src/declarative/extra/qmlfontloader.cpp index 66c8567..4a447de 100644 --- a/src/declarative/extra/qmlfontloader.cpp +++ b/src/declarative/extra/qmlfontloader.cpp @@ -92,6 +92,15 @@ QmlFontLoader::~QmlFontLoader() { } +static QString toLocalFileOrQrc(const QUrl& url) +{ + QString r = url.toLocalFile(); + if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) + r = QLatin1Char(':') + url.path(); + return r; +} + + /*! \qmlproperty url FontLoader::source The url of the font to load. @@ -112,8 +121,9 @@ void QmlFontLoader::setSource(const QUrl &url) d->status = Loading; emit statusChanged(); #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); + QString lf = toLocalFileOrQrc(d->url); + if (!lf.isEmpty()) { + QFile file(lf); file.open(QIODevice::ReadOnly); QByteArray ba = file.readAll(); d->addFontToDatabase(ba); diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 8f98a11..f1574e5 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -138,6 +138,15 @@ QFxBorderImage::~QFxBorderImage() The URL may be absolute, or relative to the URL of the component. */ +static QString toLocalFileOrQrc(const QUrl& url) +{ + QString r = url.toLocalFile(); + if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) + r = QLatin1Char(':') + url.path(); + return r; +} + + void QFxBorderImage::setSource(const QUrl &url) { Q_D(QFxBorderImage); @@ -180,8 +189,9 @@ void QFxBorderImage::setSource(const QUrl &url) d->status = Loading; if (d->url.path().endsWith(QLatin1String(".sci"))) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); + QString lf = toLocalFileOrQrc(d->url); + if (!lf.isEmpty()) { + QFile file(lf); file.open(QIODevice::ReadOnly); setGridScaledImage(QFxGridScaledImage(&file)); } else diff --git a/src/declarative/fx/qfxpixmapcache.cpp b/src/declarative/fx/qfxpixmapcache.cpp index 80b5011..13e1b16 100644 --- a/src/declarative/fx/qfxpixmapcache.cpp +++ b/src/declarative/fx/qfxpixmapcache.cpp @@ -124,6 +124,14 @@ static bool readImage(QIODevice *dev, QPixmap *pixmap) This class is NOT reentrant. */ +static QString toLocalFileOrQrc(const QUrl& url) +{ + QString r = url.toLocalFile(); + if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) + r = QLatin1Char(':') + url.path(); + return r; +} + /*! Finds the cached pixmap corresponding to \a url. A previous call to get() must have requested the URL, @@ -142,8 +150,9 @@ bool QFxPixmapCache::find(const QUrl& url, QPixmap *pixmap) bool ok = true; if (!QPixmapCache::find(key,pixmap)) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (url.scheme()==QLatin1String("file")) { - QFile f(url.toLocalFile()); + QString lf = toLocalFileOrQrc(url); + if (!lf.isEmpty()) { + QFile f(lf); if (f.open(QIODevice::ReadOnly)) { if (!readImage(&f, pixmap)) { qWarning() << "Format error loading" << url; @@ -207,10 +216,11 @@ bool QFxPixmapCache::find(const QUrl& url, QPixmap *pixmap) QNetworkReply *QFxPixmapCache::get(QmlEngine *engine, const QUrl& url, QPixmap *pixmap) { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (url.scheme()==QLatin1String("file")) { + QString lf = toLocalFileOrQrc(url); + if (!lf.isEmpty()) { QString key = url.toString(); if (!QPixmapCache::find(key,pixmap)) { - QFile f(url.toLocalFile()); + QFile f(lf); if (f.open(QIODevice::ReadOnly)) { if (!readImage(&f, pixmap)) { qWarning() << "Format error loading" << url; diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index 13bd02c..3c76344 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -262,13 +262,22 @@ void QmlCompositeTypeManager::resourceReplyFinished() reply->deleteLater(); } +static QString toLocalFileOrQrc(const QUrl& url) +{ + QString r = url.toLocalFile(); + if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) + r = QLatin1Char(':') + url.path(); + return r; +} + void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource) { QUrl url(resource->url); - if (url.scheme() == QLatin1String("file")) { + QString lf = toLocalFileOrQrc(url); + if (!lf.isEmpty()) { - QFile file(url.toLocalFile()); + QFile file(lf); if (file.open(QFile::ReadOnly)) { resource->data = file.readAll(); resource->status = QmlCompositeTypeResource::Complete; @@ -290,9 +299,10 @@ void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit) { QUrl url(unit->imports.baseUrl()); - if (url.scheme() == QLatin1String("file")) { + QString lf = toLocalFileOrQrc(url); + if (!lf.isEmpty()) { - QFile file(url.toLocalFile()); + QFile file(lf); if (file.open(QFile::ReadOnly)) { QByteArray data = file.readAll(); setData(unit, data, url); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ef0f975..2bec140 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -955,6 +955,15 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) return QVariant(); } +// XXX this beyonds in QUrl::toLocalFile() +static QString toLocalFileOrQrc(const QUrl& url) +{ + QString r = url.toLocalFile(); + if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) + r = QLatin1Char(':') + url.path(); + return r; +} + ///////////////////////////////////////////////////////////// struct QmlEnginePrivate::ImportedNamespace { QStringList urls; @@ -985,7 +994,7 @@ struct QmlEnginePrivate::ImportedNamespace { QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml")); if (vmaj || vmin) { // Check version file - XXX cache these in QmlEngine! - QFile qmldir(QUrl(urls.at(i)+QLatin1String("/qmldir")).toLocalFile()); + QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir")))); if (qmldir.open(QIODevice::ReadOnly)) { do { QByteArray lineba = qmldir.readLine(); @@ -1016,7 +1025,7 @@ struct QmlEnginePrivate::ImportedNamespace { } } else { // XXX search non-files too! (eg. zip files, see QT-524) - QFileInfo f(url.toLocalFile()); + QFileInfo f(toLocalFileOrQrc(url)); if (f.exists()) { if (url_return) *url_return = url; -- cgit v0.12 From f4d605eb2dddad17638d69d6024bc3d0efc878e6 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 14 Oct 2009 13:16:19 +1000 Subject: doc --- doc/src/declarative/network.qdoc | 81 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/doc/src/declarative/network.qdoc b/doc/src/declarative/network.qdoc index 3d75706..da4495f 100644 --- a/doc/src/declarative/network.qdoc +++ b/doc/src/declarative/network.qdoc @@ -43,11 +43,84 @@ \page qmlnetwork.html \title Network Transparency +QML supports network transparency by using URLs (rather than file names) for all +references from a QML document to other content. Since a \i relative URL is the same +as a relative file, development of QML on regular file systems remains simple. + +\section1 Accessing Network Reesources from QML + +Whenever an object has a property of type URL (QUrl), assigning a string to that +property will actually assign an absolute URL - by resolving the string against +the URL of the document where the string is used. + +For example, consider this content in \c{http://example.com/mystuff/test.qml}: + +\code +Image { + source: "images/logo.png" +} +\endcode + +The \l Image source property will be assigned \c{http://example.com/mystuff/images/logo.png}, +but while the QML is being developed, in say \c C:\User\Fred\Documents\MyStuff\test.qml, it will be assigned +\c C:\User\Fred\Documents\MyStuff\images\logo.png. + +Network transparency is supported throughout QML: + +\list +\o Types - if the \c test.qml file above used "Hello { }", that would refer to \c http://example.com/mystuff/Hello.qml +\o Scripts - the \c source property of \l Script is a URL +\o Images - the \c source property of \l Image and similar types is a URL +\o Fonts - the \c source property of FontLoader is a URL +\o WebViews - the \c url property of WebView may be assigned a relative URL string +\endlist + +Because of the declarative nature of QML and the asynchronous nature of network resources, +objects which reference network resource generally change state as the network resource loads. +For example, an Image with a network source will initially have +a \c width and \c height of 0, a \c status of \c Loading, and a \c progress of 0.0. +While the content loads, the \c progress will increase until +the content is fully loaded from the network, +at which point the \c width and \c height become the content size, the \c status becomes \c Ready, and the \c progress reaches 1.0. +Applications can bind to these changing states to provide visual progress indicators where appropriate, or simply +bind to the \c width and \c height as if the content was a local file, adapting as those bound values change. + +Note that when objects reference local files they immediately have the \c Ready status, but applications wishing +to remain network transparent should not rely on this. Future versions of QML may also use asynchronous local file I/O +to improve performance. + +\section1 Limitations + +The \c import statement only works network transparently if it has an "as" clause. + \list -\o Documents and script blocks can be fetched transparently over the network (blocking) -\o Images, fonts can be fetched transparently over the network (non-blocking) -\o Configuring the network access manager -\o Relative URL resolution from ECMAScript/QML +\o \c{import "dir"} only works on local file systems +\o \c{import libraryUri} only works on local file systems +\o \c{import "dir" as D} works network transparently +\o \c{import libraryUrl as U} works network transparently \endlist +\section1 Configuring the Network Access Manager + +All network access from QML is managed by a QNetworkAccessManager set on the QmlEngine which executes the QML. +By default, this is an unmodified Qt QNetworkAccessManager. You may set a different manager using +QmlEngine::setNetworkAccessManager() as appropriate for the policies of your application. +For eample, the \l qmlviewer tool sets a new QNetworkAccessManager which +trusts HTTP Expiry headers to avoid network cache checks, allows HTTP Pipelining, adds a persistent HTTP CookieJar, +a simple disk cache, and supports proxy settings. + +\section1 QRC Resources + +One of the URL schemes built into Qt is the "qrc" scheme. This allows content to be compiled into +the executable using \l{The Qt Resource System}. Using this, an executable can reference QML content +that is compiled into the executable: + +\code + QmlView *canvas = new QmlView; + canvas->setUrl(QUrl("qrc:/dial.qml")); +\endcode + +The content itself can then use relative URLs, and so be transparently unaware that the content is +compiled into the executable. + */ -- cgit v0.12