diff options
author | Bea Lam <bea.lam@nokia.com> | 2009-09-28 00:15:02 (GMT) |
---|---|---|
committer | Bea Lam <bea.lam@nokia.com> | 2009-09-28 00:15:02 (GMT) |
commit | 46c3f05e1edbc112df1ddb96a161d53d22340b19 (patch) | |
tree | fd917138ad3c159a1f916351cc221a225b155d48 /src/declarative/qml | |
parent | f1e06cdd804934ff8c0b350b41d3d7187a21560c (diff) | |
parent | c6090b6749c9f9bf002f999f808e456b74fea1bf (diff) | |
download | Qt-46c3f05e1edbc112df1ddb96a161d53d22340b19.zip Qt-46c3f05e1edbc112df1ddb96a161d53d22340b19.tar.gz Qt-46c3f05e1edbc112df1ddb96a161d53d22340b19.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative/qml')
-rw-r--r-- | src/declarative/qml/qbitfield_p.h | 165 | ||||
-rw-r--r-- | src/declarative/qml/qml.pri | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompileddata.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 27 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 3 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent.cpp | 68 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcomponent_p.h | 10 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompositetypedata_p.h | 11 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompositetypemanager_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlinstruction_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser.cpp | 9 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser_p.h | 3 | ||||
-rw-r--r-- | src/declarative/qml/qmlparserstatus.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlscriptparser.cpp | 7 | ||||
-rw-r--r-- | src/declarative/qml/qmlsqldatabase.cpp | 118 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme.cpp | 39 | ||||
-rw-r--r-- | src/declarative/qml/qmlvme_p.h | 8 |
19 files changed, 425 insertions, 55 deletions
diff --git a/src/declarative/qml/qbitfield_p.h b/src/declarative/qml/qbitfield_p.h new file mode 100644 index 0000000..70d5041 --- /dev/null +++ b/src/declarative/qml/qbitfield_p.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** 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 QBITFIELD_P_H +#define QBITFIELD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +class QBitField +{ +public: + inline QBitField(); + inline QBitField(const quint32 *, int bits); + inline QBitField(const QBitField &); + inline ~QBitField(); + + inline QBitField &operator=(const QBitField &); + + inline quint32 size() const; + inline QBitField united(const QBitField &); + inline bool testBit(int) const; + +private: + quint32 bits:31; + quint32 *ownData; + const quint32 *data; +}; + +QBitField::QBitField() +: bits(0), ownData(0), data(0) +{ +} + +QBitField::QBitField(const quint32 *bitData, int bitCount) +: bits((quint32)bitCount), ownData(0), data(bitData) +{ +} + +QBitField::QBitField(const QBitField &other) +: bits(other.bits), ownData(other.ownData), data(other.data) +{ + if (ownData) + ++(*ownData); +} + +QBitField::~QBitField() +{ + if (ownData) + if(0 == --(*ownData)) delete [] ownData; +} + +QBitField &QBitField::operator=(const QBitField &other) +{ + if (other.data == data) + return *this; + + if (ownData) + if(0 == --(*ownData)) delete [] ownData; + + bits = other.bits; + ownData = other.ownData; + data = other.data; + + if (ownData) + ++(*ownData); + + return *this; +} + +inline quint32 QBitField::size() const +{ + return bits; +} + +QBitField QBitField::united(const QBitField &o) +{ + if (o.bits == 0) { + return *this; + } else if (bits == 0) { + return o; + } else { + int max = (bits > o.bits)?bits:o.bits; + int length = (max + 31) / 32; + QBitField rv; + rv.bits = max; + rv.ownData = new quint32[length + 1]; + *(rv.ownData) = 1; + rv.data = rv.ownData + 1; + if (bits > o.bits) { + ::memcpy((quint32 *)rv.data, data, length * sizeof(quint32)); + for (quint32 ii = 0; ii < (o.bits + 31) / 32; ++ii) + ((quint32 *)rv.data)[ii] |= o.data[ii]; + } else { + ::memcpy((quint32 *)rv.data, o.data, length * sizeof(quint32)); + for (quint32 ii = 0; ii < (bits + 31) / 32; ++ii) + ((quint32 *)rv.data)[ii] |= data[ii]; + } + return rv; + } +} + +bool QBitField::testBit(int b) const +{ + Q_ASSERT(b >= 0); + if ((quint32)b < bits) { + return data[b / 32] & (1 << (b % 32)); + } else { + return false; + } +} + +QT_END_NAMESPACE + +#endif // QBITFIELD_P_H diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index b72c019..8349e29 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -80,6 +80,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlenginedebug_p.h \ qml/qmlrewrite_p.h \ qml/qpodvector_p.h \ + qml/qbitfield_p.h \ qml/qmlvaluetype_p.h \ qml/qmlbindingoptimizations_p.h \ qml/qmlxmlhttprequest_p.h \ diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index ffb89b3..b2e2d40 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -161,7 +161,7 @@ QmlCompiledData::~QmlCompiledData() } } -QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt) const +QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const { if (type) { QObject *rv = type->create(); @@ -170,7 +170,7 @@ QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt) const return rv; } else { Q_ASSERT(component); - return component->create(ctxt); + return QmlComponentPrivate::get(component)->create(ctxt, bindings); } } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 053c6f8..02cd813 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -645,12 +645,10 @@ void QmlCompiler::compileTree(Object *tree) output->imports = unit->imports; - if (tree->metatype) { - static_cast<QMetaObject &>(output->root) = *tree->metaObject(); + Q_ASSERT(tree->metatype); + static_cast<QMetaObject &>(output->root) = *tree->metaObject(); + if (!tree->metadata.isEmpty()) QmlEnginePrivate::get(engine)->registerCompositeType(output); - } else { - static_cast<QMetaObject &>(output->root) = *output->types.at(tree->type).metaObject(); - } } bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) @@ -791,6 +789,15 @@ void QmlCompiler::genObject(QmlParser::Object *obj) if (!obj->custom.isEmpty()) create.create.data = output->indexForByteArray(obj->custom); create.create.type = obj->type; + if (!output->types.at(create.create.type).type && + !obj->bindingBitmask.isEmpty()) { + while (obj->bindingBitmask.size() % 4) + obj->bindingBitmask.append(char(0)); + create.create.bindingBits = + output->indexForByteArray(obj->bindingBitmask); + } else { + create.create.bindingBits = -1; + } output->bytecode << create; // Setup the synthesized meta object if necessary @@ -1236,6 +1243,9 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } } + if (prop->index != -1) + prop->parent->setBindingBit(prop->index); + if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) { // The magic "id" behavior doesn't apply when "id" is resolved as a @@ -2032,7 +2042,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) builder.addSignal(p.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(p.name, type, ii); + builder.addProperty(p.name, type, builder.methodCount() - 1); propBuilder.setScriptable(true); propBuilder.setWritable(!readonly); } @@ -2157,7 +2167,10 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, data.append((const char *)&propIdx, sizeof(propIdx)); builder.addSignal(prop.name + "Changed()"); - builder.addProperty(prop.name, aliasProperty.typeName(), builder.methodCount() - 1); + QMetaPropertyBuilder propBuilder = + builder.addProperty(prop.name, aliasProperty.typeName(), + builder.methodCount() - 1); + propBuilder.setScriptable(true); return true; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 7f5e98f..00637e3 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -61,6 +61,7 @@ #include <private/qmlcompositetypemanager_p.h> #include <private/qmlparser_p.h> #include <private/qmlengine_p.h> +#include <private/qbitfield_p.h> QT_BEGIN_NAMESPACE @@ -88,7 +89,7 @@ public: QmlComponent *component; QmlRefCount *ref; - QObject *createInstance(QmlContext *) const; + QObject *createInstance(QmlContext *, const QBitField &) const; const QMetaObject *metaObject() const; }; QList<TypeReference> types; diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 1c35606..fedc2da 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -437,15 +437,22 @@ QObject *QmlComponent::create(QmlContext *context) { Q_D(QmlComponent); + return d->create(context, QBitField()); +} + +QObject *QmlComponentPrivate::create(QmlContext *context, + const QBitField &bindings) +{ + QObject *create(QmlContext *context, const QBitField &); if (!context) - context = d->engine->rootContext(); + context = engine->rootContext(); - if (context->engine() != d->engine) { + if (context->engine() != engine) { qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine"); return 0; } - QObject *rv = beginCreate(context); + QObject *rv = beginCreate(context, bindings); completeCreate(); return rv; } @@ -476,51 +483,57 @@ QObject *QmlComponent::create(QmlContext *context) QObject *QmlComponent::beginCreate(QmlContext *context) { Q_D(QmlComponent); + return d->beginCreate(context, QBitField()); +} +QObject * +QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings) +{ + Q_Q(QmlComponent); if (!context) { qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context"); return 0; } - if (context->engine() != d->engine) { + if (context->engine() != engine) { qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine"); return 0; } - if (d->completePending) { + if (completePending) { qWarning("QmlComponent: Cannot create new component instance before completing the previous"); return 0; } - if (!isReady()) { + if (!q->isReady()) { qWarning("QmlComponent: Component is not ready"); return 0; } - if (!QmlEnginePrivate::get(d->engine)->rootComponent) - QmlEnginePrivate::get(d->engine)->rootComponent = this; + if (!QmlEnginePrivate::get(engine)->rootComponent) + QmlEnginePrivate::get(engine)->rootComponent = q; QmlContextPrivate *contextPriv = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context)); QmlContext *ctxt = new QmlContext(context, 0, true); - static_cast<QmlContextPrivate*>(ctxt->d_func())->url = d->cc->url; - static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = d->cc->imports; + static_cast<QmlContextPrivate*>(ctxt->d_func())->url = cc->url; + static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->imports; QmlVME vme; - QObject *rv = vme.run(ctxt, d->cc, d->start, d->count); + QObject *rv = vme.run(ctxt, cc, start, count, bindings); if (vme.isError()) - d->errors = vme.errors(); + errors = vme.errors(); - QmlEnginePrivate *ep = QmlEnginePrivate::get(d->engine); - if (ep->rootComponent == this) { + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + if (ep->rootComponent == q) { ep->rootComponent = 0; - d->bindValues = ep->bindValues; - d->parserStatus = ep->parserStatus; + bindValues = ep->bindValues; + parserStatus = ep->parserStatus; ep->bindValues.clear(); ep->parserStatus.clear(); - d->completePending = true; + completePending = true; } if (rv) { @@ -544,14 +557,19 @@ QObject *QmlComponent::beginCreate(QmlContext *context) void QmlComponent::completeCreate() { Q_D(QmlComponent); - if (d->completePending) { + d->completeCreate(); +} + +void QmlComponentPrivate::completeCreate() +{ + if (completePending) { { #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer<QFxPerf::BindInit> bi; #endif - for (int ii = 0; ii < d->bindValues.count(); ++ii) { + for (int ii = 0; ii < bindValues.count(); ++ii) { QmlEnginePrivate::SimpleList<QmlAbstractBinding> bv = - d->bindValues.at(ii); + bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) bv.at(jj)->setEnabled(true); @@ -560,9 +578,9 @@ void QmlComponent::completeCreate() } } - for (int ii = 0; ii < d->parserStatus.count(); ++ii) { + for (int ii = 0; ii < parserStatus.count(); ++ii) { QmlEnginePrivate::SimpleList<QmlParserStatus> ps = - d->parserStatus.at(ii); + parserStatus.at(ii); for (int jj = 0; jj < ps.count; ++jj) { QmlParserStatus *status = ps.at(jj); @@ -574,9 +592,9 @@ void QmlComponent::completeCreate() QmlEnginePrivate::clear(ps); } - d->bindValues.clear(); - d->parserStatus.clear(); - d->completePending = false; + bindValues.clear(); + parserStatus.clear(); + completePending = false; } } diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h index af250e5..c6924e3 100644 --- a/src/declarative/qml/qmlcomponent.h +++ b/src/declarative/qml/qmlcomponent.h @@ -106,7 +106,7 @@ private: QmlComponent(QmlEngine *, QmlCompiledData *, int, int, QObject *parent); friend class QmlVME; - friend struct QmlCompositeTypeData; + friend class QmlCompositeTypeData; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h index 2b25b78..2d0c77f 100644 --- a/src/declarative/qml/qmlcomponent_p.h +++ b/src/declarative/qml/qmlcomponent_p.h @@ -59,6 +59,7 @@ #include <private/qobject_p.h> #include <private/qmlengine_p.h> #include <private/qmlcompositetypemanager_p.h> +#include <private/qbitfield_p.h> #include <QtDeclarative/qmlerror.h> #include <QtDeclarative/qmlcomponent.h> #include <QtDeclarative/qml.h> @@ -76,6 +77,11 @@ class QmlComponentPrivate : public QObjectPrivate public: QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), completePending(false), engine(0) {} + + QObject *create(QmlContext *context, const QBitField &); + QObject *beginCreate(QmlContext *, const QBitField &); + void completeCreate(); + QmlCompositeTypeData *typeData; void typeDataReady(); void updateProgress(qreal); @@ -98,6 +104,10 @@ public: QmlEngine *engine; void clear(); + + static QmlComponentPrivate *get(QmlComponent *c) { + return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(c)); + } }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h index 044b4ca..48c6c2b 100644 --- a/src/declarative/qml/qmlcompositetypedata_p.h +++ b/src/declarative/qml/qmlcompositetypedata_p.h @@ -58,12 +58,13 @@ QT_BEGIN_NAMESPACE -struct QmlCompositeTypeData : public QmlRefCount +class QmlCompositeTypeData : public QmlRefCount { +public: QmlCompositeTypeData(); virtual ~QmlCompositeTypeData(); - enum Status { + enum Status { Invalid, Complete, Error, @@ -83,8 +84,8 @@ struct QmlCompositeTypeData : public QmlRefCount QList<QmlCompositeTypeData *> dependants; - // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting - // state. The QmlComponent is owned by the QmlCompositeTypeData, so a + // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting + // state. The QmlComponent is owned by the QmlCompositeTypeData, so a // reference should be kept to keep the QmlComponent alive. QmlComponent *toComponent(QmlEngine *); // Return a QmlCompiledData if possible, or 0 if an error @@ -101,7 +102,7 @@ struct QmlCompositeTypeData : public QmlRefCount QList<TypeReference> types; - // Add or remove p as a waiter. When the QmlCompositeTypeData becomes + // Add or remove p as a waiter. When the QmlCompositeTypeData becomes // ready, the QmlComponentPrivate::typeDataReady() method will be invoked on // p. The waiter is automatically removed when the typeDataReady() method // is invoked, so there is no need to call remWaiter() in this case. diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h index 41cbe80..8f16998 100644 --- a/src/declarative/qml/qmlcompositetypemanager_p.h +++ b/src/declarative/qml/qmlcompositetypemanager_p.h @@ -66,7 +66,7 @@ class QmlComponentPrivate; class QmlComponent; class QmlDomDocument; -struct QmlCompositeTypeData; +class QmlCompositeTypeData; class QmlCompositeTypeManager : public QObject { diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h index 65d711c..03baafa 100644 --- a/src/declarative/qml/qmlcontext.h +++ b/src/declarative/qml/qmlcontext.h @@ -90,6 +90,7 @@ private: friend class QmlContextScriptClass; friend class QmlObjectScriptClass; friend class QmlComponent; + friend class QmlComponentPrivate; friend class QmlScriptPrivate; friend class QmlBoundSignalProxy; QmlContext(QmlContext *parent, QObject *objParent, bool); diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 3c6af1b..2c9ceac 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -170,6 +170,7 @@ public: struct { int type; int data; + int bindingBits; ushort column; } create; struct { diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 40cdd11..39fe1e2 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -84,6 +84,15 @@ QmlParser::Object::~Object() if (prop.defaultValue) prop.defaultValue->release(); } +void Object::setBindingBit(int b) +{ + while (bindingBitmask.size() < 4 * (1 + b / 32)) + bindingBitmask.append(char(0)); + + quint32 *bits = (quint32 *)bindingBitmask.data(); + bits[b / 32] |= (1 << (b % 32)); +} + const QMetaObject *Object::metaObject() const { if (!metadata.isEmpty() && metatype) diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 65223f4..e0579b0 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -130,6 +130,9 @@ namespace QmlParser int idIndex; // Custom parsed data QByteArray custom; + // Bit mask of the properties assigned bindings + QByteArray bindingBitmask; + void setBindingBit(int); // Returns the metaobject for this type, or 0 if not available. // Internally selectd between the metatype and extObject variables const QMetaObject *metaObject() const; diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h index f754227..88ed865 100644 --- a/src/declarative/qml/qmlparserstatus.h +++ b/src/declarative/qml/qmlparserstatus.h @@ -62,6 +62,7 @@ public: private: friend class QmlVME; friend class QmlComponent; + friend class QmlComponentPrivate; friend class QmlEnginePrivate; QmlParserStatus **d; }; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 09efc90..c126830 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -769,6 +769,13 @@ bool ProcessAST::visit(AST::UiSourceElement *node) } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) { // ignore variable declarations line = varStmt->declarationKindToken.startLine; + + QmlError error; + error.setDescription(QCoreApplication::translate("QmlParser", "Variable declarations not allow in inline Script blocks")); + error.setLine(node->firstSourceLocation().startLine); + error.setColumn(node->firstSourceLocation().startColumn); + _parser->_errors << error; + return false; } Value *value = new Value; diff --git a/src/declarative/qml/qmlsqldatabase.cpp b/src/declarative/qml/qmlsqldatabase.cpp index 5869a56..b132c55 100644 --- a/src/declarative/qml/qmlsqldatabase.cpp +++ b/src/declarative/qml/qmlsqldatabase.cpp @@ -46,6 +46,7 @@ #include <QtScript/qscriptvalueiterator.h> #include <QtScript/qscriptcontext.h> #include <QtScript/qscriptengine.h> +#include <QtScript/qscriptclasspropertyiterator.h> #include <QtSql/qsqldatabase.h> #include <QtSql/qsqlquery.h> #include <QtSql/qsqlerror.h> @@ -62,12 +63,14 @@ Q_DECLARE_METATYPE(QSqlDatabase) Q_DECLARE_METATYPE(QSqlQuery) +class QmlSqlQueryScriptClassPropertyIterator; + class QmlSqlQueryScriptClass: public QScriptClass { public: QmlSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine) { str_length = engine->toStringHandle(QLatin1String("length")); - str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (optimization) + str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (an optimization) } QueryFlags queryProperty(const QScriptValue &object, @@ -112,12 +115,11 @@ public: } else if (name == str_forwardOnly) { return query.isForwardOnly(); } else { - if (query.at() == id || query.seek(id)) { // Qt 4.6 doesn't optimize at()==id + if ((uint)query.at() == id || query.seek(id)) { // Qt 4.6 doesn't optimize seek(at()) QSqlRecord r = query.record(); - QScriptValue row = engine()->newArray(r.count()); + QScriptValue row = engine()->newObject(); for (int j=0; j<r.count(); ++j) { - // XXX only strings - row.setProperty(j, QScriptValue(engine(),r.value(j).toString())); + row.setProperty(r.fieldName(j), QScriptValue(engine(),r.value(j).toString())); // XXX only strings } return row; } @@ -134,11 +136,108 @@ public: } } + QScriptValue::PropertyFlags propertyFlags(const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/) + { + if (name == str_length) { + return QScriptValue::Undeletable + | QScriptValue::SkipInEnumeration; + } + return QScriptValue::Undeletable; + } + + QScriptClassPropertyIterator *newIterator(const QScriptValue &object); + private: QScriptString str_length; QScriptString str_forwardOnly; }; +class QmlSqlQueryScriptClassPropertyIterator : public QScriptClassPropertyIterator +{ +public: + QmlSqlQueryScriptClassPropertyIterator(const QScriptValue &object) + : QScriptClassPropertyIterator(object) + { + toFront(); + } + + ~QmlSqlQueryScriptClassPropertyIterator() + { + } + + bool hasNext() const + { + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object().data()); + return query.at() == m_index || query.seek(m_index); // Qt 4.6 doesn't optimize seek(at()) + } + + void next() + { + m_last = m_index; + ++m_index; + } + + bool hasPrevious() const + { + return (m_index > 0); + } + + void previous() + { + --m_index; + m_last = m_index; + } + + void toFront() + { + m_index = 0; + m_last = -1; + } + + void toBack() + { + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object().data()); + m_index = query.size(); + m_last = -1; + } + + QScriptString name() const + { + return object().engine()->toStringHandle(QString::number(m_last)); + } + + uint id() const + { + return m_last; + } + +private: + int m_index; + int m_last; +}; + +QScriptClassPropertyIterator *QmlSqlQueryScriptClass::newIterator(const QScriptValue &object) +{ + return new QmlSqlQueryScriptClassPropertyIterator(object); +} + + + +static QScriptValue qmlsqldatabase_item(QScriptContext *context, QScriptEngine *engine) +{ + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(context->thisObject().data()); + int i = context->argument(0).toNumber(); + if (query.at() == i || query.seek(i)) { // Qt 4.6 doesn't optimize seek(at()) + QSqlRecord r = query.record(); + QScriptValue row = engine->newObject(); + for (int j=0; j<r.count(); ++j) { + row.setProperty(r.fieldName(j), QScriptValue(engine,r.value(j).toString())); + } + return row; + } + return engine->undefinedValue(); +} + static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine) { QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject()); @@ -163,6 +262,7 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn QmlEnginePrivate::get(engine)->sqlQueryClass= new QmlSqlQueryScriptClass(engine); QScriptValue rows = engine->newObject(QmlEnginePrivate::get(engine)->sqlQueryClass); rows.setData(engine->newVariant(qVariantFromValue(query))); + rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration); rs.setProperty(QLatin1String("rows"),rows); rs.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected()); rs.setProperty(QLatin1String("insertId"),query.lastInsertId().toString()); // XXX only string @@ -234,7 +334,7 @@ static QScriptValue qmlsqldatabase_open(QScriptContext *context, QScriptEngine * database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid); } if (!database.isOpen()) { - QString basename = QmlEnginePrivate::get(engine)->offlineStoragePath + "/Databases/"; + QString basename = QmlEnginePrivate::get(engine)->offlineStoragePath + QLatin1String("/Databases/"); QDir().mkpath(basename); basename += dbid; database.setDatabaseName(basename+QLatin1String(".sqllite")); @@ -257,3 +357,9 @@ void qt_add_qmlsqldatabase(QScriptEngine *engine) engine->globalObject().setProperty(QLatin1String("openDatabase"), openDatabase); } +/* +HTML5 "spec" says "rs.rows[n]", but WebKit only impelments "rs.rows.item(n)". We do both (and property iterator). +We add a "forwardOnly" property that stops Qt caching results (code promises to only go forward +through the data. +*/ + diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 606a732..e266a91 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -100,14 +100,16 @@ struct ListInstance QmlPrivate::ListInterface *qmlListInterface; }; -QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp, int start, int count) +QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp, + int start, int count, + const QBitField &bindingSkipList) { QStack<QObject *> stack; if (start == -1) start = 0; if (count == -1) count = comp->bytecode.count(); - return run(stack, ctxt, comp, start, count); + return run(stack, ctxt, comp, start, count, bindingSkipList); } void QmlVME::runDeferred(QObject *object) @@ -124,10 +126,14 @@ void QmlVME::runDeferred(QObject *object) QStack<QObject *> stack; stack.push(object); - run(stack, ctxt, comp, start, count); + run(stack, ctxt, comp, start, count, QBitField()); } -QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData *comp, int start, int count) +QBitField bindingSkipList; +QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, + QmlCompiledData *comp, + int start, int count, + const QBitField &bindingSkipList) { Q_ASSERT(comp); Q_ASSERT(ctxt); @@ -166,7 +172,17 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::CreateObject: { - QObject *o = types.at(instr.create.type).createInstance(ctxt); + QBitField bindings; + if (instr.create.bindingBits != -1) { + const QByteArray &bits = datas.at(instr.create.bindingBits); + bindings = QBitField((const quint32*)bits.constData(), + bits.size() * 8); + } + if (stack.isEmpty()) + bindings = bindings.united(bindingSkipList); + + QObject *o = + types.at(instr.create.type).createInstance(ctxt, bindings); if (!o) { if(types.at(instr.create.type).component) vmeErrors << types.at(instr.create.type).component->errors(); @@ -562,6 +578,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData QmlMetaProperty mp; mp.restore(instr.assignBinding.property, target, ctxt); + int coreIndex = mp.coreIndex(); + + if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) + break; + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; @@ -572,6 +593,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::StoreIdOptBinding: { + int coreIndex = instr.assignIdOptBinding.property; + if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) + break; + QObject *target = stack.top(); QmlBinding_Id *bind = @@ -585,6 +610,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::StoreObjPropBinding: { + int coreIndex = instr.assignObjPropBinding.property; + if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) + break; + QObject *target = stack.top(); QObject *context = stack.at(stack.count() - 1 - instr.assignObjPropBinding.context); diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h index 30a6e4f..38ba06f 100644 --- a/src/declarative/qml/qmlvme_p.h +++ b/src/declarative/qml/qmlvme_p.h @@ -56,6 +56,7 @@ #include <QtCore/QString> #include <QtCore/QStack> #include <QtDeclarative/qmlerror.h> +#include <private/qbitfield_p.h> QT_BEGIN_NAMESPACE @@ -70,14 +71,17 @@ class QmlVME public: QmlVME(); - QObject *run(QmlContext *, QmlCompiledData *, int start = -1, int count = -1); + QObject *run(QmlContext *, QmlCompiledData *, + int start = -1, int count = -1, + const QBitField & = QBitField()); void runDeferred(QObject *); bool isError() const; QList<QmlError> errors() const; private: - QObject *run(QStack<QObject *> &, QmlContext *, QmlCompiledData *, int start, int count); + QObject *run(QStack<QObject *> &, QmlContext *, QmlCompiledData *, + int start, int count, const QBitField &); QList<QmlError> vmeErrors; }; |