summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorBea Lam <bea.lam@nokia.com>2009-09-28 00:15:02 (GMT)
committerBea Lam <bea.lam@nokia.com>2009-09-28 00:15:02 (GMT)
commit46c3f05e1edbc112df1ddb96a161d53d22340b19 (patch)
treefd917138ad3c159a1f916351cc221a225b155d48 /src/declarative/qml
parentf1e06cdd804934ff8c0b350b41d3d7187a21560c (diff)
parentc6090b6749c9f9bf002f999f808e456b74fea1bf (diff)
downloadQt-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.h165
-rw-r--r--src/declarative/qml/qml.pri1
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp4
-rw-r--r--src/declarative/qml/qmlcompiler.cpp27
-rw-r--r--src/declarative/qml/qmlcompiler_p.h3
-rw-r--r--src/declarative/qml/qmlcomponent.cpp68
-rw-r--r--src/declarative/qml/qmlcomponent.h2
-rw-r--r--src/declarative/qml/qmlcomponent_p.h10
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h11
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h2
-rw-r--r--src/declarative/qml/qmlcontext.h1
-rw-r--r--src/declarative/qml/qmlinstruction_p.h1
-rw-r--r--src/declarative/qml/qmlparser.cpp9
-rw-r--r--src/declarative/qml/qmlparser_p.h3
-rw-r--r--src/declarative/qml/qmlparserstatus.h1
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp7
-rw-r--r--src/declarative/qml/qmlsqldatabase.cpp118
-rw-r--r--src/declarative/qml/qmlvme.cpp39
-rw-r--r--src/declarative/qml/qmlvme_p.h8
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;
};