summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2009-10-09 01:26:00 (GMT)
committerMartin Jones <martin.jones@nokia.com>2009-10-09 01:26:00 (GMT)
commitdda314e206162215e60dd306b6347a04f19ca5df (patch)
treee50652d9b6b72ccbd5622d1bf28feec34fc3a998 /src/declarative
parent8e56f62a7155ec8f8e8af07100675fd6185bf481 (diff)
parentd131a9f99ebd5d753d2eedfafe0b276410168bc8 (diff)
downloadQt-dda314e206162215e60dd306b6347a04f19ca5df.zip
Qt-dda314e206162215e60dd306b6347a04f19ca5df.tar.gz
Qt-dda314e206162215e60dd306b6347a04f19ca5df.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp76
-rw-r--r--src/declarative/qml/qml.pri21
-rw-r--r--src/declarative/qml/qmlbinding.cpp59
-rw-r--r--src/declarative/qml/qmlbinding.h1
-rw-r--r--src/declarative/qml/qmlbinding_p.h15
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp9
-rw-r--r--src/declarative/qml/qmlcompiler.cpp108
-rw-r--r--src/declarative/qml/qmlcompiler_p.h16
-rw-r--r--src/declarative/qml/qmlcomponent.cpp3
-rw-r--r--src/declarative/qml/qmlcomponentjs_p.h8
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h22
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp152
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h6
-rw-r--r--src/declarative/qml/qmlcontext.cpp97
-rw-r--r--src/declarative/qml/qmlcontext_p.h18
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp211
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h98
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h5
-rw-r--r--src/declarative/qml/qmlengine.cpp662
-rw-r--r--src/declarative/qml/qmlengine_p.h153
-rw-r--r--src/declarative/qml/qmlexpression.cpp236
-rw-r--r--src/declarative/qml/qmlexpression_p.h48
-rw-r--r--src/declarative/qml/qmlglobalscriptclass.cpp94
-rw-r--r--src/declarative/qml/qmlglobalscriptclass_p.h (renamed from src/declarative/util/qmlscript.h)55
-rw-r--r--src/declarative/qml/qmlinstruction.cpp2
-rw-r--r--src/declarative/qml/qmlinstruction_p.h8
-rw-r--r--src/declarative/qml/qmlintegercache.cpp106
-rw-r--r--src/declarative/qml/qmlintegercache_p.h106
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp662
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h65
-rw-r--r--src/declarative/qml/qmlmetatype.cpp206
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp303
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h111
-rw-r--r--src/declarative/qml/qmlparser.cpp2
-rw-r--r--src/declarative/qml/qmlparser_p.h5
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp213
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h152
-rw-r--r--src/declarative/qml/qmlscript.cpp82
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp51
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h2
-rw-r--r--src/declarative/qml/qmltypenamecache.cpp94
-rw-r--r--src/declarative/qml/qmltypenamecache_p.h112
-rw-r--r--src/declarative/qml/qmltypenamescriptclass.cpp163
-rw-r--r--src/declarative/qml/qmltypenamescriptclass_p.h91
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass.cpp151
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass_p.h89
-rw-r--r--src/declarative/qml/qmlvme.cpp20
-rw-r--r--src/declarative/util/qmlpackage.cpp2
-rw-r--r--src/declarative/util/qmlscript.cpp205
-rw-r--r--src/declarative/util/util.pri2
50 files changed, 3618 insertions, 1560 deletions
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
index b7248ea..943f909 100644
--- a/src/declarative/fx/qfxvisualitemmodel.cpp
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -239,6 +239,10 @@ class QFxVisualDataModelPrivate : public QObjectPrivate
public:
QFxVisualDataModelPrivate(QmlContext *);
+ static QFxVisualDataModelPrivate *get(QFxVisualDataModel *m) {
+ return static_cast<QFxVisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
QGuard<QListModelInterface> m_listModelInterface;
QGuard<QAbstractItemModel> m_abstractItemModel;
QGuard<QFxVisualDataModel> m_visualItemModel;
@@ -363,7 +367,8 @@ class QFxVisualDataModelData : public QObject
{
Q_OBJECT
public:
- QFxVisualDataModelData(int index, QFxVisualDataModelPrivate *model);
+ QFxVisualDataModelData(int index, QFxVisualDataModel *model);
+ ~QFxVisualDataModelData();
Q_PROPERTY(int index READ index NOTIFY indexChanged)
int index() const;
@@ -379,7 +384,7 @@ Q_SIGNALS:
private:
friend class QFxVisualDataModelDataMetaObject;
int m_index;
- QFxVisualDataModelPrivate *m_model;
+ QGuard<QFxVisualDataModel> m_model;
QFxVisualDataModelDataMetaObject *m_meta;
};
@@ -404,15 +409,19 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha
QFxVisualDataModelData *data =
static_cast<QFxVisualDataModelData *>(object());
- if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
- && data->m_model->m_listAccessor) {
- data->m_model->ensureRoles();
- if (data->m_model->m_roleNames.contains(QLatin1String(name)))
+ if (!data->m_model)
+ return -1;
+
+ QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model);
+
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ model->ensureRoles();
+ if (model->m_roleNames.contains(QLatin1String(name)))
return QmlOpenMetaObject::createProperty(name, type);
} else {
- data->m_model->ensureRoles();
+ model->ensureRoles();
const QLatin1String sname(name);
- if (data->m_model->m_roleNames.contains(sname))
+ if (model->m_roleNames.contains(sname))
return QmlOpenMetaObject::createProperty(name, type);
}
return -1;
@@ -425,45 +434,48 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
QFxVisualDataModelData *data =
static_cast<QFxVisualDataModelData *>(object());
+
+ Q_ASSERT(data->m_model);
+ QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model);
+
QString name = QLatin1String(prop.name());
- if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
- && data->m_model->m_listAccessor) {
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
if (name == QLatin1String("modelData")) {
- if (data->m_model->m_listAccessor->type() == QmlListAccessor::Instance) {
- QObject *object = data->m_model->m_listAccessor->at(0).value<QObject*>();
+ if (model->m_listAccessor->type() == QmlListAccessor::Instance) {
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
return object->metaObject()->property(1).read(object); // the first property after objectName
}
- return data->m_model->m_listAccessor->at(data->m_index);
+ return model->m_listAccessor->at(data->m_index);
} else {
// return any property of a single object instance.
- QObject *object = data->m_model->m_listAccessor->at(0).value<QObject*>();
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
return object->property(prop.name());
}
- } else if (data->m_model->m_listModelInterface) {
- data->m_model->ensureRoles();
- QHash<QString,int>::const_iterator it = data->m_model->m_roleNames.find(name);
- if (it != data->m_model->m_roleNames.end()) {
+ } else if (model->m_listModelInterface) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
roles.append(*it);
- QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << *it);
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << *it);
if (values.isEmpty())
return QVariant();
else
return values.value(*it);
- } else if (data->m_model->m_roles.count() == 1 && name == QLatin1String("modelData")) {
+ } else if (model->m_roles.count() == 1 && name == QLatin1String("modelData")) {
//for compatability with other lists, assign modelData if there is only a single role
- QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << data->m_model->m_roles.first());
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << model->m_roles.first());
if (values.isEmpty())
return QVariant();
else
return *values.begin();
}
- } else if (data->m_model->m_abstractItemModel) {
- data->m_model->ensureRoles();
- QHash<QString,int>::const_iterator it = data->m_model->m_roleNames.find(name);
- if (it != data->m_model->m_roleNames.end()) {
+ } else if (model->m_abstractItemModel) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
roles.append(*it);
- QModelIndex index = data->m_model->m_abstractItemModel->index(data->m_index, 0);
- return data->m_model->m_abstractItemModel->data(index, *it);
+ QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0);
+ return model->m_abstractItemModel->data(index, *it);
}
}
Q_ASSERT(!"Can never be reached");
@@ -471,12 +483,16 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
}
QFxVisualDataModelData::QFxVisualDataModelData(int index,
- QFxVisualDataModelPrivate *model)
+ QFxVisualDataModel *model)
: m_index(index), m_model(model),
m_meta(new QFxVisualDataModelDataMetaObject(this))
{
}
+QFxVisualDataModelData::~QFxVisualDataModelData()
+{
+}
+
int QFxVisualDataModelData::index() const
{
return m_index;
@@ -752,7 +768,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp
QmlContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
- QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d);
+ QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this);
ctxt->setContextProperty(QLatin1String("model"), data);
ctxt->addDefaultObject(data);
nobj = d->m_delegate->beginCreate(ctxt);
@@ -821,7 +837,7 @@ QVariant QFxVisualDataModel::evaluate(int index, const QString &expression, QObj
QmlContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
- QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d);
+ QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this);
ctxt->addDefaultObject(data);
QmlExpression e(ctxt, expression, objectContext);
e.setTrackChange(false);
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 8349e29..a2e2050 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -34,7 +34,16 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlxmlhttprequest.cpp \
qml/qmlsqldatabase.cpp \
qml/qmetaobjectbuilder.cpp \
- qml/qmlwatcher.cpp
+ qml/qmlwatcher.cpp \
+ qml/qmlscript.cpp \
+ qml/qmlpropertycache.cpp \
+ qml/qmlintegercache.cpp \
+ qml/qmltypenamecache.cpp \
+ qml/qmlobjectscriptclass.cpp \
+ qml/qmlcontextscriptclass.cpp \
+ qml/qmlglobalscriptclass.cpp \
+ qml/qmlvaluetypescriptclass.cpp \
+ qml/qmltypenamescriptclass.cpp
HEADERS += qml/qmlparser_p.h \
qml/qmlinstruction_p.h \
@@ -86,7 +95,15 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlxmlhttprequest_p.h \
qml/qmlsqldatabase_p.h \
qml/qmetaobjectbuilder_p.h \
- qml/qmlwatcher_p.h
+ qml/qmlwatcher_p.h \
+ qml/qmlpropertycache_p.h \
+ qml/qmlintegercache_p.h \
+ qml/qmltypenamecache_p.h \
+ qml/qmlobjectscriptclass_p.h \
+ qml/qmlcontextscriptclass_p.h \
+ qml/qmlglobalscriptclass_p.h \
+ qml/qmlvaluetypescriptclass_p.h \
+ qml/qmltypenamescriptclass_p.h
# for qtscript debugger
contains(QT_CONFIG, scripttools):QT += scripttools
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 454369b..3a34f46 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -57,11 +57,16 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_NOCREATE_TYPE(QmlBinding);
-QmlBindingPrivate::QmlBindingPrivate()
+QmlBindingData::QmlBindingData()
: updating(false), enabled(false)
{
}
+QmlBindingPrivate::QmlBindingPrivate()
+: QmlExpressionPrivate(new QmlBindingData)
+{
+}
+
QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate)
{
@@ -81,7 +86,7 @@ QmlBinding::~QmlBinding()
void QmlBinding::setTarget(const QmlMetaProperty &prop)
{
Q_D(QmlBinding);
- d->property = prop;
+ d->bindingData()->property = prop;
update();
}
@@ -89,7 +94,7 @@ void QmlBinding::setTarget(const QmlMetaProperty &prop)
QmlMetaProperty QmlBinding::property() const
{
Q_D(const QmlBinding);
- return d->property;
+ return d->bindingData()->property;
}
void QmlBinding::update()
@@ -99,45 +104,41 @@ void QmlBinding::update()
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
#endif
- if (!d->enabled)
+ QmlBindingData *data = d->bindingData();
+
+ if (!data->enabled)
return;
- if (!d->updating) {
- d->updating = true;
+ data->addref();
- if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {
+ if (!data->updating) {
+ data->updating = true;
- int idx = d->property.coreIndex();
+ if (data->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ int idx = data->property.coreIndex();
Q_ASSERT(idx != -1);
void *a[1];
QmlBinding *t = this;
a[0] = (void *)&t;
- QMetaObject::metacall(d->property.object(),
+ QMetaObject::metacall(data->property.object(),
QMetaObject::WriteProperty,
idx, a);
} else {
QVariant value = this->value();
- if (value.type() == QVariant::String) {
- QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(d->property.propertyType());
- if (con)
- value = con(value.toString());
- }
-
- if (d->property.propertyType() == QVariant::Vector3D &&
- value.type() == QVariant::String) {
- value = qVariantFromValue(QmlStringConverters::vector3DFromString(value.toString()));
- }
-
- d->property.write(value, QmlMetaProperty::Binding);
+ data->property.write(value, QmlMetaProperty::Binding);
}
- d->updating = false;
+ data->updating = false;
} else {
- qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
+ qmlInfo(data->property.object()) << "Binding loop detected for property"
+ << data->property.name();
}
+
+ data->release();
}
void QmlBinding::valueChanged()
@@ -148,30 +149,30 @@ void QmlBinding::valueChanged()
void QmlBinding::setEnabled(bool e)
{
Q_D(QmlBinding);
- d->enabled = e;
+ d->bindingData()->enabled = e;
setTrackChange(e);
+ QmlAbstractBinding::setEnabled(e);
+
if (e) {
- addToObject(d->property.object());
+ addToObject(d->bindingData()->property.object());
update();
} else {
removeFromObject();
}
-
- QmlAbstractBinding::setEnabled(e);
}
int QmlBinding::propertyIndex()
{
Q_D(QmlBinding);
- return d->property.coreIndex();
+ return d->bindingData()->property.coreIndex();
}
bool QmlBinding::enabled() const
{
Q_D(const QmlBinding);
- return d->enabled;
+ return d->bindingData()->enabled;
}
QString QmlBinding::expression() const
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index 675917d..e3a297c 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -73,6 +73,7 @@ public:
private:
friend class QmlDeclarativeData;
friend class QmlMetaProperty;
+ friend class QmlMetaPropertyPrivate;
friend class QmlVME;
QObject *m_object;
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
index 963e2c1..2c0c6b9 100644
--- a/src/declarative/qml/qmlbinding_p.h
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -59,11 +59,10 @@
QT_BEGIN_NAMESPACE
-class QmlBindingPrivate : public QmlExpressionPrivate
+class QmlBindingData : public QmlExpressionData
{
- Q_DECLARE_PUBLIC(QmlBinding)
public:
- QmlBindingPrivate();
+ QmlBindingData();
bool updating:1;
bool enabled:1;
@@ -71,6 +70,16 @@ public:
QmlMetaProperty property;
};
+class QmlBindingPrivate : public QmlExpressionPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBinding)
+public:
+ QmlBindingPrivate();
+
+ QmlBindingData *bindingData() { return static_cast<QmlBindingData *>(data); }
+ const QmlBindingData *bindingData() const { return static_cast<const QmlBindingData *>(data); }
+};
+
QT_END_NAMESPACE
#endif // QMLBINDING_P_H
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
index b2e2d40..8c3c355 100644
--- a/src/declarative/qml/qmlcompileddata.cpp
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -150,6 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
}
QmlCompiledData::QmlCompiledData()
+: importCache(0)
{
}
@@ -159,6 +160,14 @@ QmlCompiledData::~QmlCompiledData()
if (types.at(ii).ref)
types.at(ii).ref->release();
}
+
+ for (int ii = 0; ii < propertyCaches.count(); ++ii)
+ propertyCaches.at(ii)->release();
+
+ if (importCache)
+ importCache->release();
+
+ qDeleteAll(programs);
}
QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 02cd813..12e8101 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -633,7 +633,7 @@ void QmlCompiler::compileTree(Object *tree)
init.line = 0;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
output->bytecode << init;
genObject(tree);
@@ -644,10 +644,11 @@ void QmlCompiler::compileTree(Object *tree)
output->bytecode << def;
output->imports = unit->imports;
+ output->importCache = output->imports.cache(engine);
Q_ASSERT(tree->metatype);
static_cast<QMetaObject &>(output->root) = *tree->metaObject();
- if (!tree->metadata.isEmpty())
+ if (!tree->metadata.isEmpty())
QmlEnginePrivate::get(engine)->registerCompositeType(output);
}
@@ -668,7 +669,11 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
if (obj->metatype == &QmlComponent::staticMetaObject) {
COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
- }
+ }
+
+ // Build any script blocks for this type
+ for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii)
+ COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii)));
// Object instantiations reset the binding context
BindingContext objCtxt(obj);
@@ -807,7 +812,9 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
meta.line = -1;
meta.storeMeta.data = output->indexForByteArray(obj->metadata);
meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
- meta.storeMeta.slotData = -1;
+ meta.storeMeta.propertyCache = output->propertyCaches.count();
+ // ### Surely the creation of this property cache could be more efficient
+ output->propertyCaches << QmlPropertyCache::create(engine, obj->metaObject());
output->bytecode << meta;
}
@@ -821,6 +828,15 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
output->bytecode << id;
}
+ // Set any script blocks
+ for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) {
+ QmlInstruction script;
+ script.type = QmlInstruction::StoreScript;
+ script.line = -1; // ###
+ script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii));
+ output->bytecode << script;
+ }
+
// Begin the class
if (obj->parserStatusCast != -1) {
QmlInstruction begin;
@@ -962,7 +978,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj)
init.type = QmlInstruction::Init;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
init.line = obj->location.start.line;
output->bytecode << init;
@@ -997,7 +1013,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
// Find, check and set the "id" property (if any)
Property *idProp = 0;
if (obj->properties.count() > 1 ||
- (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id") ||
+ !obj->scriptBlockObjects.isEmpty())
COMPILE_EXCEPTION(obj, "Invalid component specification");
if (obj->properties.count())
@@ -1034,6 +1051,66 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
return true;
}
+bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
+{
+ QString scriptCode;
+
+ if (script->properties.count() == 1 &&
+ script->properties.begin().key() == QByteArray("source")) {
+
+ Property *source = *script->properties.begin();
+ if (script->defaultProperty)
+ COMPILE_EXCEPTION(source, "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");
+
+ QString 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) {
+ scriptCode = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+
+ } else if (!script->properties.isEmpty()) {
+ COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block");
+ } else if (script->defaultProperty) {
+ QmlParser::Location currentLocation;
+
+ for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
+ Value *v = script->defaultProperty->values.at(ii);
+ if (v->object || !v->value.isString())
+ COMPILE_EXCEPTION(v, "Invalid Script block");
+
+ if (ii == 0) {
+ currentLocation = v->location.start;
+ scriptCode.append(QString(currentLocation.column, QLatin1Char(' ')));
+ }
+
+ while (currentLocation.line < v->location.start.line) {
+ scriptCode.append(QLatin1String("\n"));
+ currentLocation.line++;
+ currentLocation.column = 0;
+ }
+
+ scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' ')));
+
+ scriptCode += v->value.asString();
+ currentLocation = v->location.end;
+ currentLocation.column++;
+ }
+ }
+
+ if (!scriptCode.isEmpty())
+ obj->scriptBlocks.append(scriptCode);
+
+ return true;
+}
+
bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
const BindingContext &ctxt)
{
@@ -2261,6 +2338,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
output->bytecode << store;
}
+int QmlCompiler::genContextCache()
+{
+ if (compileState.ids.count() == 0)
+ return -1;
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ for (QHash<QString, QmlParser::Object *>::ConstIterator iter = compileState.ids.begin();
+ iter != compileState.ids.end();
+ ++iter)
+ cache->add(iter.key(), (*iter)->idIndex);
+
+ output->contextCaches.append(cache);
+ return output->contextCaches.count() - 1;
+}
+
bool QmlCompiler::completeComponentBuild()
{
for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
@@ -2296,7 +2389,10 @@ bool QmlCompiler::completeComponentBuild()
expression = rewriteBinding(expression);
quint32 length = expression.length();
+ quint32 pc = output->programs.length();
+ output->programs.append(0);
binding.compiledData =
+ QByteArray((const char *)&pc, sizeof(quint32)) +
QByteArray((const char *)&length, sizeof(quint32)) +
QByteArray((const char *)expression.constData(),
expression.length() * sizeof(QChar));
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 00637e3..1d27342 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -62,6 +62,9 @@
#include <private/qmlparser_p.h>
#include <private/qmlengine_p.h>
#include <private/qbitfield_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmlintegercache_p.h>
+#include <private/qmltypenamecache_p.h>
QT_BEGIN_NAMESPACE
@@ -69,6 +72,7 @@ class QmlEngine;
class QmlComponent;
class QmlContext;
+class QScriptProgram;
class QmlCompiledData : public QmlRefCount
{
public:
@@ -78,6 +82,7 @@ public:
QByteArray name;
QUrl url;
QmlEnginePrivate::Imports imports;
+ QmlTypeNameCache *importCache;
struct TypeReference
{
@@ -98,6 +103,7 @@ public:
int index;
int type;
};
+
QAbstractDynamicMetaObject root;
QList<QString> primitives;
QList<float> floatData;
@@ -106,6 +112,9 @@ public:
QList<QByteArray> datas;
QList<QmlParser::Location> locations;
QList<QmlInstruction> bytecode;
+ QList<QScriptProgram *> programs;
+ QList<QmlPropertyCache *> propertyCaches;
+ QList<QmlIntegerCache *> contextCaches;
void dumpInstructions();
private:
@@ -162,6 +171,7 @@ private:
bool buildObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildScript(QmlParser::Object *obj, QmlParser::Object *script);
bool buildComponent(QmlParser::Object *obj, const BindingContext &);
bool buildSubObject(QmlParser::Object *obj, const BindingContext &);
bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
@@ -227,7 +237,7 @@ private:
QmlParser::Property *prop,
QmlParser::Object *obj,
QmlParser::Property *valueTypeProperty = 0);
-
+ int genContextCache();
int componentTypeRef();
@@ -253,12 +263,10 @@ private:
struct ComponentCompileState
{
ComponentCompileState()
- : parserStatusCount(0), savedObjects(0),
- pushedProperties(0), root(0) {}
+ : parserStatusCount(0), pushedProperties(0), root(0) {}
QHash<QString, QmlParser::Object *> ids;
QHash<int, QmlParser::Object *> idIndexes;
int parserStatusCount;
- int savedObjects;
int pushedProperties;
QHash<QmlParser::Value *, BindingReference> bindings;
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index fedc2da..5b1cbeb 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -517,7 +517,8 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings)
static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
QmlContext *ctxt = new QmlContext(context, 0, true);
static_cast<QmlContextPrivate*>(ctxt->d_func())->url = cc->url;
- static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->imports;
+ static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->importCache;
+ cc->importCache->addref();
QmlVME vme;
QObject *rv = vme.run(ctxt, cc, start, count, bindings);
diff --git a/src/declarative/qml/qmlcomponentjs_p.h b/src/declarative/qml/qmlcomponentjs_p.h
index 0f56766..3213929 100644
--- a/src/declarative/qml/qmlcomponentjs_p.h
+++ b/src/declarative/qml/qmlcomponentjs_p.h
@@ -69,14 +69,14 @@ class Q_DECLARATIVE_EXPORT QmlComponentJS : public QmlComponent
{
Q_OBJECT
Q_DECLARE_PRIVATE(QmlComponentJS)
- friend class QmlEngine;
-public:
- QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0);
- QmlComponentJS(QmlEngine *, QObject *parent=0);
Q_PROPERTY(bool isNull READ isNull NOTIFY isNullChanged)
Q_PROPERTY(bool isReady READ isReady NOTIFY isReadyChanged)
Q_PROPERTY(bool isError READ isError NOTIFY isErrorChanged)
Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged)
+ friend class QmlEngine;
+public:
+ QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponentJS(QmlEngine *, QObject *parent=0);
Q_INVOKABLE QScriptValue createObject();
Q_INVOKABLE QString errorsString() const;
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
index 48c6c2b..fa11137 100644
--- a/src/declarative/qml/qmlcompositetypedata_p.h
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -58,6 +58,7 @@
QT_BEGIN_NAMESPACE
+class QmlCompositeTypeResource;
class QmlCompositeTypeData : public QmlRefCount
{
public:
@@ -101,6 +102,7 @@ public:
};
QList<TypeReference> types;
+ QList<QmlCompositeTypeResource *> resources;
// Add or remove p as a waiter. When the QmlCompositeTypeData becomes
// ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
@@ -122,5 +124,25 @@ private:
QmlCompiledData *compiledComponent;
};
+class QmlCompositeTypeResource : public QmlRefCount
+{
+public:
+ QmlCompositeTypeResource();
+ virtual ~QmlCompositeTypeResource();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ QString url;
+ QByteArray data;
+};
+
#endif // QMLCOMPOSITETYPEDATA_P_H
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index a99cff0..71b4ef0 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -63,6 +63,9 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
for (int ii = 0; ii < dependants.count(); ++ii)
dependants.at(ii)->release();
+ for (int ii = 0; ii < resources.count(); ++ii)
+ resources.at(ii)->release();
+
if (compiledComponent)
compiledComponent->release();
@@ -70,6 +73,16 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
delete component;
}
+QmlCompositeTypeResource::QmlCompositeTypeResource()
+{
+}
+
+QmlCompositeTypeResource::~QmlCompositeTypeResource()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+}
+
void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
{
waiters << p;
@@ -142,6 +155,10 @@ QmlCompositeTypeManager::~QmlCompositeTypeManager()
(*iter)->release();
iter = components.erase(iter);
}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ }
}
QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
@@ -181,8 +198,16 @@ void QmlCompositeTypeManager::clearCache()
++iter;
}
}
-}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ if ((*iter)->status != QmlCompositeTypeResource::Waiting) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
void QmlCompositeTypeManager::replyFinished()
{
@@ -215,6 +240,52 @@ void QmlCompositeTypeManager::replyFinished()
reply->deleteLater();
}
+void QmlCompositeTypeManager::resourceReplyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeResource *resource = resources.value(reply->url().toString());
+ Q_ASSERT(resource);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ resource->status = QmlCompositeTypeResource::Error;
+
+ } else {
+
+ resource->status = QmlCompositeTypeResource::Complete;
+ resource->data = reply->readAll();
+
+ }
+
+ doComplete(resource);
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource)
+{
+ QUrl url(resource->url);
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if (file.open(QFile::ReadOnly)) {
+ resource->data = file.readAll();
+ resource->status = QmlCompositeTypeResource::Complete;
+ } else {
+ resource->status = QmlCompositeTypeResource::Error;
+ }
+
+ } else {
+
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(resourceReplyFinished()));
+
+ }
+}
+
void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
{
QUrl url(unit->imports.baseUrl());
@@ -308,6 +379,15 @@ void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
}
}
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource)
+{
+ for (int ii = 0; ii < resource->dependants.count(); ++ii) {
+ checkComplete(resource->dependants.at(ii));
+ resource->dependants.at(ii)->release();
+ }
+ resource->dependants.clear();
+}
+
void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
{
if (unit->status != QmlCompositeTypeData::Waiting)
@@ -329,12 +409,33 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
waiting++;
}
}
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ QmlCompositeTypeResource *r = unit->resources.at(ii);
+
+ if (!r)
+ continue;
+
+ if (r->status == QmlCompositeTypeResource::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + r->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ doComplete(unit);
+ return;
+ } else if (r->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+
if (!waiting) {
unit->status = QmlCompositeTypeData::Complete;
doComplete(unit);
}
}
+// ### Check ref counting in here
void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
{
QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
@@ -346,12 +447,6 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
QmlCompositeTypeData::TypeReference ref;
- if (typeName == QByteArray("Property") ||
- typeName == QByteArray("Signal")) {
- unit->types << ref;
- continue;
- }
-
QUrl url;
int majorVersion;
int minorVersion;
@@ -431,6 +526,49 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->types << ref;
}
+ QList<QUrl> resourceList = unit->data.referencedResources();
+ for (int ii = 0; ii < resourceList.count(); ++ii) {
+ QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii));
+
+ QmlCompositeTypeResource *resource = resources.value(url.toString());
+
+ if (!resource) {
+ resource = new QmlCompositeTypeResource;
+ resource->status = QmlCompositeTypeResource::Waiting;
+ resource->url = url.toString();
+ resources.insert(resource->url, resource);
+
+ loadResource(resource);
+ }
+
+ switch(resource->status) {
+ case QmlCompositeTypeResource::Invalid:
+ case QmlCompositeTypeResource::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + resource->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ }
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ resource->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ resource->addref();
+ unit->resources << resource;
+ }
+
if (waiting) {
unit->status = QmlCompositeTypeData::Waiting;
} else {
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index 8f16998..843a9cf 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -67,6 +67,7 @@ class QmlComponent;
class QmlDomDocument;
class QmlCompositeTypeData;
+class QmlCompositeTypeResource;
class QmlCompositeTypeManager : public QObject
{
@@ -88,19 +89,24 @@ public:
private Q_SLOTS:
void replyFinished();
+ void resourceReplyFinished();
void requestProgress(qint64 received, qint64 total);
private:
void loadSource(QmlCompositeTypeData *);
+ void loadResource(QmlCompositeTypeResource *);
void compile(QmlCompositeTypeData *);
void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
void doComplete(QmlCompositeTypeData *);
+ void doComplete(QmlCompositeTypeResource *);
void checkComplete(QmlCompositeTypeData *);
QmlEngine *engine;
typedef QHash<QString, QmlCompositeTypeData *> Components;
Components components;
+ typedef QHash<QString, QmlCompositeTypeResource *> Resources;
+ Resources resources;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 0632ef7..f6795aa 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -48,6 +48,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlinfo.h>
// 6-bits
#define MAXIMUM_DEFAULT_OBJECTS 63
@@ -55,11 +56,49 @@
QT_BEGIN_NAMESPACE
QmlContextPrivate::QmlContextPrivate()
-: parent(0), engine(0), isInternal(false), notifyIndex(-1),
- highPriorityCount(0), expressions(0), idValues(0), idValueCount(0)
+: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1),
+ highPriorityCount(0), imports(0), expressions(0), idValues(0), idValueCount(0)
{
}
+void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject)
+{
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(scriptValue);
+
+ if (scopeObject)
+ scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject));
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+
+ QScriptValue val = scriptEngine->evaluate(script);
+
+ 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();
+ }
+ }
+ }
+
+ scriptEngine->popContext();
+
+ scripts.append(scope);
+}
+
void QmlContextPrivate::dump()
{
dump(0);
@@ -103,16 +142,7 @@ void QmlContextPrivate::init()
//set scope chain
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- QScriptValue scopeObj =
- scriptEngine->newObject(QmlEnginePrivate::get(engine)->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
- //### no longer need to push global object once we switch to JSC (test with objects added to globalObject)
- //if (parent)
- // scopeChain = parent->d_func()->scopeChain;
- if (!parent)
- scopeChain.append(scriptEngine->globalObject());
- else
- scopeChain = parent->d_func()->scopeChain;
- scopeChain.prepend(scopeObj);
+ scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q);
}
void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
@@ -304,6 +334,12 @@ QmlContext::~QmlContext()
d->contextObjects.clear();
delete [] d->idValues;
+
+ if (d->propertyNames)
+ d->propertyNames->release();
+
+ if (d->imports)
+ d->imports->release();
}
void QmlContextPrivate::invalidateEngines()
@@ -361,13 +397,16 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value)
QObject *o = QmlMetaType::toQObject(value);
setContextProperty(name, o);
} else {
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+
+ int idx = d->propertyNames->value(name);
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(value);
} else {
- d->propertyValues[*iter] = value;
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = value;
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
}
@@ -380,15 +419,18 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx,
notifyIndex = q->metaObject()->methodCount();
}
- propertyNames.insert(name, idx);
idValues[idx].priv = this;
idValues[idx] = obj;
}
-void QmlContextPrivate::setIdPropertyCount(int count)
+void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data)
{
- idValues = new ContextGuard[count];
- idValueCount = count;
+ Q_ASSERT(!propertyNames);
+ propertyNames = data;
+ propertyNames->addref();
+
+ idValueCount = data->count();
+ idValues = new ContextGuard[idValueCount];
}
/*!
@@ -402,14 +444,15 @@ void QmlContext::setContextProperty(const QString &name, QObject *value)
if (d->notifyIndex == -1)
d->notifyIndex = this->metaObject()->methodCount();
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+ int idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(QVariant::fromValue(value));
} else {
- int idx = *iter;
- d->propertyValues[*iter] = QVariant::fromValue(value);
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = QVariant::fromValue(value);
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index b305408..d18bfda 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -61,6 +61,8 @@
#include <QtCore/qset.h>
#include <private/qguard_p.h>
#include <private/qmlengine_p.h>
+#include <private/qmlintegercache_p.h>
+#include <private/qmltypenamecache_p.h>
QT_BEGIN_NAMESPACE
@@ -82,17 +84,21 @@ public:
QmlEngine *engine;
bool isInternal;
- QHash<QString, int> propertyNames;
+ QmlIntegerCache *propertyNames;
QList<QVariant> propertyValues;
int notifyIndex;
QObjectList defaultObjects;
int highPriorityCount;
- QScriptValueList scopeChain;
+ QScriptValue scriptValue;
+
+ QList<QScriptValue> scripts;
+ void addScript(const QString &script, QObject *scope);
QUrl url;
- QmlEnginePrivate::Imports imports;
+
+ QmlTypeNameCache *imports;
void init();
@@ -125,9 +131,13 @@ public:
ContextGuard *idValues;
int idValueCount;
void setIdProperty(const QString &, int, QObject *);
- void setIdPropertyCount(int);
+ void setIdPropertyData(QmlIntegerCache *);
void destroyed(ContextGuard *);
+ static QmlContextPrivate *get(QmlContext *context) {
+ return static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ }
+
// Only used for debugging
QList<QPointer<QObject> > instances;
};
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
new file mode 100644
index 0000000..6d2c58c
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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 "qmlcontextscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmltypenamescriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ContextData : public QScriptDeclarativeClass::Object {
+ ContextData(QmlContext *c) : context(c) {}
+ QGuard<QmlContext> context;
+};
+
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
+ lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData(context));
+}
+
+QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ return data->context;
+}
+
+#include <QDebug>
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ lastContext = 0;
+ lastData = 0;
+ lastPropertyIndex = -1;
+ lastDefaultObject = -1;
+
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ if (!bindContext)
+ return 0;
+
+ while (bindContext) {
+ QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags);
+ if (rv) return rv;
+ bindContext = bindContext->parentContext();
+ }
+
+ return 0;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1;
+ if (lastPropertyIndex != -1) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+
+ if (data) {
+ lastData = data;
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0);
+
+ if (rv) {
+ lastDefaultObject = ii;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ 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;
+}
+
+QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+
+ if (lastData) {
+
+ if (lastData->type)
+ return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type);
+ else
+ return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace);
+
+ } else if (lastPropertyIndex != -1) {
+
+ QScriptValue rv;
+ if (lastPropertyIndex < cp->idValueCount) {
+ rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data());
+ } else {
+ QVariant value = cp->propertyValues.at(lastPropertyIndex);
+ rv = ep->scriptValueFromVariant(value);
+ }
+
+ ep->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex);
+
+ return rv;
+ } else if(lastDefaultObject != -1) {
+
+ // Default object property
+ return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name);
+
+ } else {
+
+ return lastFunction;
+
+ }
+}
+
+void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_ASSERT(lastDefaultObject != -1);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ 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
new file mode 100644
index 0000000..761a115
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 QMLCONTEXTSCRIPTCLASS_P_H
+#define QMLCONTEXTSCRIPTCLASS_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 <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlContextScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ QScriptValue newContext(QmlContext *);
+
+ QmlContext *contextFromValue(const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ QmlEngine *engine;
+
+ QmlContext *lastContext;
+ QmlTypeNameCache::Data *lastData;
+ int lastPropertyIndex;
+ int lastDefaultObject;
+ QScriptValue lastFunction;
+
+ uint m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
index ade961f..f6ecc3d 100644
--- a/src/declarative/qml/qmldeclarativedata_p.h
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -54,12 +54,14 @@
//
#include <private/qobject_p.h>
+#include <QtScript/qscriptvalue.h>
QT_BEGIN_NAMESPACE
class QmlCompiledData;
class QmlAbstractBinding;
class QmlContext;
+class QmlPropertyCache;
class QmlDeclarativeData : public QDeclarativeData
{
public:
@@ -85,6 +87,9 @@ public:
QHash<int, QObject *> *attachedProperties;
+ QScriptValue scriptValue;
+ QmlPropertyCache *propertyCache;
+
static QmlDeclarativeData *get(const QObject *object, bool create = false) {
QObjectPrivate *priv =
QObjectPrivate::get(const_cast<QObject *>(object));
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index f34d790..ccdf6cf 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -41,11 +41,13 @@
#undef QT3_SUPPORT // don't want it here - it just causes bugs (which is why we removed it)
-#include <QMetaProperty>
+#include <QtCore/qmetaobject.h>
#include <private/qmlengine_p.h>
#include <private/qmlcontext_p.h>
#include <private/qobject_p.h>
#include <private/qmlcompiler_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlglobalscriptclass_p.h>
#ifdef QT_SCRIPTTOOLS_LIB
#include <QScriptEngineDebugger>
@@ -83,6 +85,7 @@
#include <private/qmlstringconverters_p.h>
#include <private/qmlxmlhttprequest_p.h>
#include <private/qmlsqldatabase_p.h>
+#include <private/qmltypenamescriptclass_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
#include "qt_windows.h"
@@ -121,7 +124,7 @@ static QString userLocalDataPath(const QString& app)
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentExpression(0),
- isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(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)
{
@@ -148,6 +151,14 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
qtObject.setProperty(QLatin1String("lighter"), scriptEngine.newFunction(QmlEnginePrivate::lighter, 1));
qtObject.setProperty(QLatin1String("darker"), scriptEngine.newFunction(QmlEnginePrivate::darker, 1));
qtObject.setProperty(QLatin1String("tint"), scriptEngine.newFunction(QmlEnginePrivate::tint, 2));
+
+ scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
+ scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
+ scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
+ scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
+
+ //scriptEngine.globalObject().setScriptClass(new QmlGlobalScriptClass(&scriptEngine));
+ globalClass = new QmlGlobalScriptClass(&scriptEngine);
}
QmlEnginePrivate::~QmlEnginePrivate()
@@ -177,6 +188,9 @@ QmlEnginePrivate::~QmlEnginePrivate()
clear(parserStatus[ii]);
for(QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
(*iter)->release();
+ for(QHash<const QMetaObject *, QmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
+ (*iter)->release();
+
}
void QmlEnginePrivate::clear(SimpleList<QmlAbstractBinding> &bvs)
@@ -212,11 +226,6 @@ void QmlEnginePrivate::init()
}
#endif
- scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
- scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
- scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
- scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
-
if (QCoreApplication::instance()->thread() == q->thread() &&
QmlEngineDebugServer::isDebuggingEnabled()) {
qmlEngineDebugServer();
@@ -232,203 +241,6 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
{
}
-struct QmlTypeNameBridge
-{
- QObject *object;
- QmlType *type;
- QmlEnginePrivate::ImportedNamespace *ns;
-};
-Q_DECLARE_METATYPE(QmlTypeNameBridge);
-
-struct QmlValueTypeReference {
- QmlValueType *type;
- QGuard<QObject> object;
- int property;
-};
-Q_DECLARE_METATYPE(QmlValueTypeReference);
-
-////////////////////////////////////////////////////////////////////
-QScriptClass::QueryFlags
-QmlEnginePrivate::queryContext(const QString &propName, uint *id,
- QmlContext *bindContext)
-{
- resolveData.safetyCheckId++;
- *id = resolveData.safetyCheckId;
- resolveData.clear();
-
- QHash<QString, int>::Iterator contextProperty =
- bindContext->d_func()->propertyNames.find(propName);
-
- if (contextProperty != bindContext->d_func()->propertyNames.end()) {
-
- resolveData.context = bindContext;
- resolveData.contextIndex = *contextProperty;
-
- return QScriptClass::HandlesReadAccess;
- }
-
- QmlType *type = 0; ImportedNamespace *ns = 0;
- if (currentExpression && bindContext == currentExpression->context() &&
- propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) {
-
- if (type || ns) {
- // Must be either an attached property, or an enum
- resolveData.object = bindContext->d_func()->defaultObjects.first();
- resolveData.type = type;
- resolveData.ns = ns;
- return QScriptClass::HandlesReadAccess;
- }
-
- }
-
- QScriptClass::QueryFlags rv = 0;
- for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
- rv = queryObject(propName, id,
- bindContext->d_func()->defaultObjects.at(ii));
- }
-
- return rv;
-}
-
-QScriptValue QmlEnginePrivate::propertyContext(const QScriptString &name, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
-
- if (resolveData.type || resolveData.ns) {
- QmlTypeNameBridge tnb = {
- resolveData.object,
- resolveData.type,
- resolveData.ns
- };
- return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb)));
- } else if (resolveData.context) {
- QmlContext *bindContext = resolveData.context;
- QmlContextPrivate *contextPrivate = bindContext->d_func();
- int index = resolveData.contextIndex;
-
- QScriptValue rv;
- if (index < contextPrivate->idValueCount) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data())));
- } else {
- QVariant value = contextPrivate->propertyValues.at(index);
- if (QmlMetaType::isObject(value.userType())) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value));
- } else {
- rv = scriptEngine.newVariant(value);
- }
- }
- capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex);
- return rv;
-
- } else {
-
- return propertyObject(name, resolveData.object, id);
-
- }
-
- return QScriptValue();
-}
-
-void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id)
-{
- // As context properties cannot be written, we can assume that the
- // write is a object property write
- setPropertyObject(value, id);
-}
-
-void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
- Q_Q(QmlEngine);
-
- resolveData.property.write(QmlScriptClass::toVariant(q, value));
-}
-
-QScriptClass::QueryFlags
-QmlEnginePrivate::queryObject(const QString &propName,
- uint *id, QObject *obj)
-{
- resolveData.safetyCheckId++;
- *id = resolveData.safetyCheckId;
- resolveData.clear();
-
- QScriptClass::QueryFlags rv = 0;
-
- QmlContext *ctxt = QmlEngine::contextForObject(obj);
- if (!ctxt)
- ctxt = rootContext;
- QmlMetaProperty prop(obj, propName, ctxt);
-
- if (prop.type() == QmlMetaProperty::Invalid) {
- QPair<const QMetaObject *, QString> key =
- qMakePair(obj->metaObject(), propName);
- bool isFunction = false;
- if (functionCache.contains(key)) {
- isFunction = functionCache.value(key);
- } else {
- QScriptValue sobj = scriptEngine.newQObject(obj);
- QScriptValue func = sobj.property(propName);
- isFunction = func.isFunction();
- functionCache.insert(key, isFunction);
- }
-
- if (isFunction) {
- resolveData.object = obj;
- resolveData.isFunction = true;
- rv |= QScriptClass::HandlesReadAccess;
- }
- } else {
- resolveData.object = obj;
- resolveData.property = prop;
-
- rv |= QScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QScriptClass::HandlesWriteAccess;
- }
-
- return rv;
-}
-
-QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
- QObject *obj, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
- Q_ASSERT(resolveData.object);
-
- if (resolveData.isFunction) {
- // ### Optimize
- QScriptValue sobj = scriptEngine.newQObject(obj);
- QScriptValue func = sobj.property(propName);
- return func;
- } else {
- const QmlMetaProperty &prop = resolveData.property;
-
- if (prop.needsChangedNotifier())
- capturedProperties << CapturedProperty(prop);
-
- int propType = prop.propertyType();
- if (propType < QVariant::UserType && valueTypes[propType]) {
- QmlValueTypeReference ref;
- ref.type = valueTypes[propType];
- ref.object = obj;
- ref.property = prop.coreIndex();
- return scriptEngine.newObject(valueTypeClass, scriptEngine.newVariant(QVariant::fromValue(ref)));
- }
-
- QVariant var = prop.read();
- QObject *varobj = (propType < QVariant::UserType)?0:QmlMetaType::toQObject(var);
- if (!varobj)
- varobj = qvariant_cast<QObject *>(var);
- if (varobj) {
- return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
- } else {
- return qScriptValueFromValue(&scriptEngine, var);
- }
- }
-
- return QScriptValue();
-}
-
/*!
\class QmlEngine
\brief The QmlEngine class provides an environment for instantiating QML components.
@@ -666,7 +478,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt)
: context(ctxt), bindings(0), bindingBitsSize(0), bindingBits(0),
outerContext(0), lineNumber(0), columnNumber(0), deferredComponent(0),
- deferredIdx(0), attachedProperties(0)
+ deferredIdx(0), attachedProperties(0), propertyCache(0)
{
}
@@ -691,6 +503,9 @@ void QmlDeclarativeData::destroyed(QObject *object)
if (bindingBits)
free(bindingBits);
+ if (propertyCache)
+ propertyCache->release();
+
delete this;
}
@@ -719,9 +534,10 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
bindingBits = (quint32 *)realloc(bindingBits,
arraySize * sizeof(quint32));
+
memset(bindingBits + oldArraySize,
- sizeof(quint32) * (arraySize - oldArraySize),
- 0x00);
+ 0x00,
+ sizeof(quint32) * (arraySize - oldArraySize));
bindingBitsSize = arraySize * 32;
}
@@ -740,8 +556,8 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
QmlEngine* engine)
{
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- return scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newQObject(object, QScriptEngine::AutoOwnership));
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ return enginePriv->objectClass->newQObject(object);
}
/*!
@@ -857,7 +673,7 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi
QUrl url;
if(ctxt->argumentCount() > 2)
url = QUrl(ctxt->argument(2).toString());
- QObject *parentArg = ctxt->argument(1).data().toQObject();
+ QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
QmlContext *qmlCtxt = qmlContext(parentArg);
url = qmlCtxt->resolvedUrl(url);
QmlComponent component(activeEngine, qml.toUtf8(), url);
@@ -1083,346 +899,63 @@ QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
}
-QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
-: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)),
- engine(bindengine)
+
+QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val)
{
+ if (QmlMetaType::isObject(val.userType())) {
+ QObject *rv = *(QObject **)val.constData();
+ return objectClass->newQObject(rv);
+ } else {
+ return qScriptValueFromValue(&scriptEngine, val);
+ }
}
-QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
+QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val)
{
- QmlEnginePrivate *ep =
- static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == objectClass)
+ return QVariant::fromValue(objectClass->toQObject(val));
+ else if (dc == contextClass)
+ return QVariant();
QScriptClass *sc = val.scriptClass();
if (!sc) {
return val.toVariant();
- } else if (sc == ep->contextClass) {
+ } else if (sc == valueTypeClass) {
+ return valueTypeClass->toVariant(val);
+ } else {
return QVariant();
- } else if (sc == ep->objectClass) {
- return QVariant::fromValue(val.data().toQObject());
- } else if (sc == ep->valueTypeClass) {
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(val.data().toVariant());
-
- if (!ref.object)
- return QVariant();
-
- QMetaProperty p = ref.object->metaObject()->property(ref.property);
- return p.read(ref.object);
}
-
- return QVariant();
-}
-
-/////////////////////////////////////////////////////////////
-/*
- The QmlContextScriptClass handles property access for a QmlContext
- via QtScript.
- */
-QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
-}
-
-QmlContextScriptClass::~QmlContextScriptClass()
-{
}
-QScriptClass::QueryFlags
-QmlContextScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QmlContext *bindContext =
- static_cast<QmlContext*>(object.data().toQObject());
-
- QString propName = name.toString();
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->queryContext(propName, id, bindContext);
-}
-
-QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- Q_UNUSED(object);
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->propertyContext(name, id);
-}
-
-void QmlContextScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_UNUSED(name);
-
- QmlEnginePrivate::get(engine)->setPropertyContext(value, id);
-}
-
-/////////////////////////////////////////////////////////////
-QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine)
-: QmlScriptClass(engine), object(0), type(0)
-{
-}
-
-QmlTypeNameScriptClass::~QmlTypeNameScriptClass()
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)),
+ engine(bindengine)
{
}
-QmlTypeNameScriptClass::QueryFlags
-QmlTypeNameScriptClass::queryProperty(const QScriptValue &scriptObject,
- const QScriptString &name,
- QueryFlags flags, uint *id)
+QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
{
- Q_UNUSED(flags);
-
- QmlTypeNameBridge bridge =
- qvariant_cast<QmlTypeNameBridge>(scriptObject.data().toVariant());
-
- object = 0;
- type = 0;
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
-
- if (bridge.ns) {
- QmlType *type = 0;
- ep->resolveTypeInNamespace(bridge.ns, name.toString().toUtf8(),
- &type, 0, 0, 0);
- if (type) {
- object = bridge.object;
- this->type = type;
- return HandlesReadAccess;
- } else {
- return 0;
- }
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
- } else {
- Q_ASSERT(bridge.type);
- QString strName = name.toString();
- if (strName.at(0).isUpper()) {
- // Must be an enum
- // ### Optimize
- const char *enumName = strName.toUtf8().constData();
- const QMetaObject *metaObject = bridge.type->baseMetaObject();
- for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- int value = e.keyToValue(enumName);
- if (value != -1) {
- enumValue = value;
- return HandlesReadAccess;
- }
- }
- return 0;
- } else {
- // Must be an attached property
- this->object = qmlAttachedPropertiesObjectById(bridge.type->index(), bridge.object);
- if (!this->object)
- return 0;
- return ep->queryObject(strName, id, this->object);
- }
- }
-}
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == ep->objectClass)
+ return QVariant::fromValue(ep->objectClass->toQObject(val));
+ else if (dc == ep->contextClass)
+ return QVariant();
-QScriptValue QmlTypeNameScriptClass::property(const QScriptValue &,
- const QScriptString &propName,
- uint id)
-{
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- if (type) {
- QmlTypeNameBridge tnb = { object, type, 0 };
- return ep->scriptEngine.newObject(ep->typeNameClass, ep->scriptEngine.newVariant(qVariantFromValue(tnb)));
- } else if (object) {
- return ep->propertyObject(propName, object, id);
- } else {
- return QScriptValue(enumValue);
+ QScriptClass *sc = val.scriptClass();
+ if (!sc) {
+ return val.toVariant();
+ } else if (sc == ep->valueTypeClass) {
+ return ep->valueTypeClass->toVariant(val);
}
-}
-
-/////////////////////////////////////////////////////////////
-QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine)
-: QmlScriptClass(bindEngine)
-{
-}
-
-QmlValueTypeScriptClass::~QmlValueTypeScriptClass()
-{
-}
-
-QmlValueTypeScriptClass::QueryFlags
-QmlValueTypeScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return 0;
- QByteArray propName = name.toString().toUtf8();
-
- int idx = ref.type->metaObject()->indexOfProperty(propName.constData());
- if (idx == -1)
- return 0;
- *id = idx;
-
- QMetaProperty prop = ref.object->metaObject()->property(idx);
-
- QmlValueTypeScriptClass::QueryFlags rv =
- QmlValueTypeScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QmlValueTypeScriptClass::HandlesWriteAccess;
-
- return rv;
-}
-
-QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- Q_UNUSED(name);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return QScriptValue();
-
- ref.type->read(ref.object, ref.property);
-
- QMetaProperty p = ref.type->metaObject()->property(id);
- QVariant rv = p.read(ref.type);
-
- return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv);
-}
-
-void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(name);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return;
-
- QVariant v = QmlScriptClass::toVariant(engine, value);
-
- 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);
+ return QVariant();
}
/////////////////////////////////////////////////////////////
-/*
- The QmlObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-
-QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- QString ret = QLatin1String("Qml Object, ");
- if(obj){
- //###Should this be designer or developer details? Dev for now.
- //TODO: Can we print the id too?
- ret += QLatin1String("\"");
- ret += obj->objectName();
- ret += QLatin1String("\" ");
- ret += QLatin1String(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
- ret += QLatin1String(")");
- }else{
- ret += QLatin1String("null");
- }
- return engine->newVariant(ret);
-}
-
-QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- if(obj){
- int delay = 0;
- if(context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- //### Should this be delayed as well?
- context->thisObject().setData(QScriptValue(engine, 0));
- }
- return engine->nullValue();
-}
-
-QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
- engine = bindEngine;
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
- prototypeObject = scriptEngine->newObject();
- prototypeObject.setProperty(QLatin1String("toStr"),//TODO: Why won't toString work?
- scriptEngine->newFunction(QmlObjectToString));
- prototypeObject.setProperty(QLatin1String("destroy"),
- scriptEngine->newFunction(QmlObjectDestroy));
-}
-
-QmlObjectScriptClass::~QmlObjectScriptClass()
-{
-}
-
-QScriptValue QmlObjectScriptClass::prototype() const
-{
- return prototypeObject;
-}
-
-QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QObject *obj = object.data().toQObject();
- QueryFlags rv = 0;
- QString propName = name.toString();
-
- if (obj)
- rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, obj);
-
- return rv;
-}
-
-QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- QObject *obj = object.data().toQObject();
-
- QScriptValue rv =
- QmlEnginePrivate::get(engine)->propertyObject(name, obj, id);
- if (rv.isValid())
- return rv;
-
- return QScriptValue();
-}
-
-void QmlObjectScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(name);
- Q_UNUSED(object);
- QmlEnginePrivate::get(engine)->setPropertyObject(value, id);
-}
-
-
struct QmlEnginePrivate::ImportedNamespace {
QStringList urls;
QList<int> majversions;
@@ -1589,6 +1122,7 @@ public:
int ref;
private:
+ friend class QmlEnginePrivate::Imports;
QmlEnginePrivate::ImportedNamespace unqualifiedset;
QHash<QString,QmlEnginePrivate::ImportedNamespace* > set;
};
@@ -1619,6 +1153,80 @@ QmlEnginePrivate::Imports::~Imports()
delete d;
}
+#include <QtDeclarative/qmlmetatype.h>
+#include <private/qmltypenamecache_p.h>
+static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePrivate::ImportedNamespace &set, QmlTypeNameCache *cache)
+{
+ if (!cache)
+ cache = new QmlTypeNameCache(engine);
+
+ QList<QmlType *> types = QmlMetaType::qmlTypes();
+
+ for (int ii = 0; ii < set.urls.count(); ++ii) {
+ if (!set.isBuiltin.at(ii))
+ continue;
+
+ QByteArray base = set.urls.at(ii).toUtf8() + "/";
+ int major = set.majversions.at(ii);
+ int minor = set.minversions.at(ii);
+
+ foreach (QmlType *type, types) {
+ if (type->qmlTypeName().startsWith(base) &&
+ type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
+ type->majorVersion() == major && type->minMinorVersion() <= minor &&
+ type->maxMinorVersion() >= minor) {
+
+ QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length()));
+
+ cache->add(name, type);
+ }
+ }
+ }
+
+ return cache;
+}
+
+QmlTypeNameCache *QmlEnginePrivate::Imports::cache(QmlEngine *engine) const
+{
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ QmlTypeNameCache *cache = new QmlTypeNameCache(engine);
+
+ for (QHash<QString,QmlEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin();
+ iter != d->set.end(); ++iter) {
+
+ QmlTypeNameCache::Data *d = cache->data(iter.key());
+ if (d) {
+ if (!d->typeNamespace)
+ cacheForNamespace(engine, *(*iter), d->typeNamespace);
+ } else {
+ QmlTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0);
+ cache->add(iter.key(), nc);
+ nc->release();
+ }
+ }
+
+ cacheForNamespace(engine, set, cache);
+
+ return cache;
+}
+
+/*
+QStringList QmlEnginePrivate::Imports::unqualifiedSet() const
+{
+ QStringList rv;
+
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ for (int ii = 0; ii < set.urls.count(); ++ii) {
+ if (set.isBuiltin.at(ii))
+ rv << set.urls.at(ii);
+ }
+
+ return rv;
+}
+*/
+
/*!
Sets the base URL to be used for all relative file imports added.
*/
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 74e24d4..7978023 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -72,6 +72,10 @@
#include <QtDeclarative/qmlexpression.h>
#include <QtScript/qscriptengine.h>
#include <private/qmlmetaproperty_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmlobjectscriptclass_p.h>
+#include <private/qmlcontextscriptclass_p.h>
+#include <private/qmlvaluetypescriptclass_p.h>
QT_BEGIN_NAMESPACE
@@ -88,6 +92,9 @@ class QScriptEngineDebugger;
class QNetworkReply;
class QNetworkAccessManager;
class QmlAbstractBinding;
+class QScriptDeclarativeClass;
+class QmlTypeNameScriptClass;
+class QmlTypeNameCache;
class QmlEnginePrivate : public QObjectPrivate
{
@@ -98,17 +105,6 @@ public:
void init();
- QScriptClass::QueryFlags queryContext(const QString &name, uint *id,
- QmlContext *);
- QScriptValue propertyContext(const QScriptString &propName, uint id);
- void setPropertyContext(const QScriptValue &, uint id);
- QScriptClass::QueryFlags queryObject(const QString &name, uint *id,
- QObject *);
- QScriptValue propertyObject(const QScriptString &propName, QObject *,
- uint id = 0);
- void setPropertyObject(const QScriptValue &, uint id);
-
-
struct CapturedProperty {
CapturedProperty(QObject *o, int c, int n)
: object(o), coreIndex(c), notifyIndex(n) {}
@@ -128,29 +124,12 @@ public:
#endif
struct ImportedNamespace;
- struct ResolveData {
- ResolveData() : safetyCheckId(0) {}
- int safetyCheckId;
-
- void clear() {
- object = 0; context = 0;
- type = 0; ns = 0;
- contextIndex = -1; isFunction = false;
- }
- QObject *object;
- QmlContext *context;
-
- QmlType *type;
- QmlEnginePrivate::ImportedNamespace *ns;
-
- int contextIndex;
- bool isFunction;
- QmlMetaProperty property;
- } resolveData;
QmlContextScriptClass *contextClass;
QmlObjectScriptClass *objectClass;
QmlValueTypeScriptClass *valueTypeClass;
QmlTypeNameScriptClass *typeNameClass;
+ // Global script class
+ QScriptClass *globalClass;
// Used by DOM Core 3 API
QScriptClass *nodeListClass;
QScriptClass *namedNodeMapClass;
@@ -209,15 +188,21 @@ public:
}
QmlValueTypeFactory valueTypes;
- // ### Fixme
- typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
- FunctionCache functionCache;
- QHash<const QMetaObject *, QmlMetaObjectCache> propertyCache;
- static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) {
- if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0;
- return &priv->propertyCache[obj->metaObject()];
+
+ QHash<const QMetaObject *, QmlPropertyCache *> propertyCache;
+ QmlPropertyCache *cache(QObject *obj) {
+ Q_Q(QmlEngine);
+ if (!obj || QObjectPrivate::get(obj)->metaObject) return 0;
+ const QMetaObject *mo = obj->metaObject();
+ QmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) {
+ rv = QmlPropertyCache::create(q, mo);
+ propertyCache.insert(mo, rv);
+ }
+ return rv;
}
+ // ### This whole class is embarrassing
struct Imports {
Imports();
~Imports();
@@ -227,6 +212,8 @@ public:
void setBaseUrl(const QUrl& url);
QUrl baseUrl() const;
+ QmlTypeNameCache *cache(QmlEngine *) const;
+
private:
friend class QmlEnginePrivate;
QmlImportsPrivate *d;
@@ -251,6 +238,9 @@ public:
QHash<int, int> m_qmlLists;
QHash<int, QmlCompiledData *> m_compositeTypes;
+ QScriptValue scriptValueFromVariant(const QVariant &);
+ QVariant scriptValueToVariant(const QScriptValue &);
+
static QScriptValue qmlScriptObject(QObject*, QmlEngine*);
static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*);
@@ -275,19 +265,6 @@ public:
class QmlScriptClass : public QScriptClass
{
public:
- enum ClassId
- {
- InvalidId = -1,
-
- FunctionId = 0x80000000,
- VariantPropertyId = 0x40000000,
- PropertyId = 0x00000000,
-
- ClassIdMask = 0xC0000000,
-
- ClassIdSelectorMask = 0x3F000000,
- };
-
QmlScriptClass(QmlEngine *);
static QVariant toVariant(QmlEngine *, const QScriptValue &);
@@ -295,82 +272,6 @@ protected:
QmlEngine *engine;
};
-class QmlContextScriptClass : public QmlScriptClass
-{
-public:
- QmlContextScriptClass(QmlEngine *);
- ~QmlContextScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
-class QmlObjectScriptClass : public QmlScriptClass
-{
-public:
- QmlObjectScriptClass(QmlEngine *);
- ~QmlObjectScriptClass();
-
- virtual QScriptValue prototype () const;
- QScriptValue prototypeObject;
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
-class QmlTypeNameScriptClass : public QmlScriptClass
-{
-public:
- QmlTypeNameScriptClass(QmlEngine *);
- ~QmlTypeNameScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
-
-private:
- QObject *object;
- QmlType *type;
- quint32 enumValue;
-};
-
-class QmlValueTypeScriptClass : public QmlScriptClass
-{
-public:
- QmlValueTypeScriptClass(QmlEngine *);
- ~QmlValueTypeScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
QT_END_NAMESPACE
#endif // QMLENGINE_P_H
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index db9d39f..23e1700 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -45,46 +45,85 @@
#include "qmlcontext_p.h"
#include "qmlrewrite_p.h"
#include "QtCore/qdebug.h"
+#include "qmlcompiler_p.h"
Q_DECLARE_METATYPE(QList<QObject *>);
QT_BEGIN_NAMESPACE
-QmlExpressionPrivate::QmlExpressionPrivate()
+QmlExpressionData::QmlExpressionData()
: expressionFunctionValid(false), expressionRewritten(false), me(0),
trackChange(true), line(-1), guardList(0), guardListLength(0)
{
}
+QmlExpressionData::~QmlExpressionData()
+{
+ if (guardList) { delete [] guardList; guardList = 0; }
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate()
+: data(new QmlExpressionData)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpressionData *d)
+: data(d)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ if (data) { data->q = 0; data->release(); data = 0; }
+}
+
void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr,
QObject *me)
{
- expression = expr;
+ data->expression = expr;
- QmlAbstractExpression::setContext(ctxt);
- this->me = me;
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
}
void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
QObject *me)
{
- quint32 *data = (quint32 *)expr;
- Q_ASSERT(*data == BasicScriptEngineData ||
- *data == PreTransformedQtScriptData);
- if (*data == BasicScriptEngineData) {
- sse.load((const char *)(data + 1), rc);
+ quint32 *exprData = (quint32 *)expr;
+ Q_ASSERT(*exprData == BasicScriptEngineData ||
+ *exprData == PreTransformedQtScriptData);
+ if (*exprData == BasicScriptEngineData) {
+ data->sse.load((const char *)(exprData + 1), rc);
} else {
- expression = QString::fromRawData((QChar *)(data + 2), data[1]);
- expressionRewritten = true;
- }
+ QmlCompiledData *dd = (QmlCompiledData *)rc;
- QmlAbstractExpression::setContext(ctxt);
- this->me = me;
-}
+ data->expressionRewritten = true;
+ data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]);
-QmlExpressionPrivate::~QmlExpressionPrivate()
-{
- if (guardList) { delete [] guardList; guardList = 0; }
+ int progIdx = *(exprData + 1);
+ QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ if (!dd->programs.at(progIdx)) {
+ dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression));
+ }
+
+ QmlContextPrivate *ctxtPriv = ctxt->d_func();
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
+ if (me)
+ scriptContext->pushScope(ep->objectClass->newQObject(me));
+
+ data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
+
+ data->expressionFunctionValid = true;
+ scriptEngine->popContext();
+ }
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
}
/*!
@@ -151,7 +190,7 @@ QmlExpression::~QmlExpression()
QmlEngine *QmlExpression::engine() const
{
Q_D(const QmlExpression);
- return d->context()?d->context()->engine():0;
+ return d->data->context()?d->data->context()->engine():0;
}
/*!
@@ -161,7 +200,7 @@ QmlEngine *QmlExpression::engine() const
QmlContext *QmlExpression::context() const
{
Q_D(const QmlExpression);
- return d->context();
+ return d->data->context();
}
/*!
@@ -170,10 +209,10 @@ QmlContext *QmlExpression::context() const
QString QmlExpression::expression() const
{
Q_D(const QmlExpression);
- if (d->sse.isValid())
- return QLatin1String(d->sse.expression());
+ if (d->data->sse.isValid())
+ return QLatin1String(d->data->sse.expression());
else
- return d->expression;
+ return d->data->expression;
}
/*!
@@ -193,12 +232,12 @@ void QmlExpression::setExpression(const QString &expression)
d->clearGuards();
- d->expression = expression;
- d->expressionFunctionValid = false;
- d->expressionRewritten = false;
- d->expressionFunction = QScriptValue();
+ d->data->expression = expression;
+ d->data->expressionFunctionValid = false;
+ d->data->expressionRewritten = false;
+ d->data->expressionFunction = QScriptValue();
- d->sse.clear();
+ d->data->sse.clear();
}
QVariant QmlExpressionPrivate::evalSSE()
@@ -207,7 +246,7 @@ QVariant QmlExpressionPrivate::evalSSE()
QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
#endif
- QVariant rv = sse.run(context(), me);
+ QVariant rv = data->sse.run(data->context(), data->me);
return rv;
}
@@ -218,37 +257,39 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
#endif
- QmlContextPrivate *ctxtPriv = context()->d_func();
- QmlEngine *engine = context()->engine();
+ QmlContextPrivate *ctxtPriv = data->context()->d_func();
+ QmlEngine *engine = data->context()->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- if (me)
- ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me);
if (secondaryScope)
ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount,
secondaryScope);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- if (!expressionFunctionValid) {
+ if (!data->expressionFunctionValid) {
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i)
- scriptContext->pushScope(ctxtPriv->scopeChain.at(i));
+ if (data->me)
+ scriptContext->pushScope(ep->objectClass->newQObject(data->me));
- if (expressionRewritten) {
- expressionFunction = scriptEngine->evaluate(expression, fileName, line);
+ if (data->expressionRewritten) {
+ data->expressionFunction = scriptEngine->evaluate(data->expression,
+ data->fileName, data->line);
} else {
QmlRewrite::RewriteBinding rewriteBinding;
- const QString code = rewriteBinding(expression);
- expressionFunction = scriptEngine->evaluate(code, fileName, line);
+ const QString code = rewriteBinding(data->expression);
+ data->expressionFunction = scriptEngine->evaluate(code, data->fileName, data->line);
}
scriptEngine->popContext();
- expressionFunctionValid = true;
+ data->expressionFunctionValid = true;
}
- QScriptValue svalue = expressionFunction.call();
+ QScriptValue svalue = data->expressionFunction.call();
if (scriptEngine->hasUncaughtException()) {
if (scriptEngine->uncaughtException().isError()){
@@ -264,8 +305,6 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
}
}
- if (me)
- ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
if (secondaryScope)
ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
@@ -277,13 +316,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QList<QObject *> list;
for (int ii = 0; ii < length; ++ii) {
QScriptValue arrayItem = svalue.property(ii);
- QObject *d =
- qvariant_cast<QObject *>(arrayItem.data().toVariant());
- if (d) {
- list << d;
- } else {
- list << 0;
- }
+ QObject *d = arrayItem.toQObject();
+ list << d;
}
rv = QVariant::fromValue(list);
}
@@ -297,13 +331,10 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
!svalue.isQMetaObject() &&
!svalue.isQObject() &&
!svalue.isRegExp()) {
- QScriptValue objValue = svalue.data();
- if (objValue.isValid()) {
- QVariant var = objValue.toVariant();
- if (var.userType() >= (int)QVariant::UserType &&
- QmlMetaType::isObject(var.userType()))
- rv = var;
- }
+
+ QObject *o = svalue.toQObject();
+ if (o)
+ return qVariantFromValue(o);
}
if (rv.isNull())
rv = svalue.toVariant();
@@ -316,7 +347,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
Q_Q(QmlExpression);
QVariant rv;
- if (!q->engine() || (!sse.isValid() && expression.isEmpty()))
+ if (!q->engine() || (!data->sse.isValid() && data->expression.isEmpty()))
return rv;
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -331,7 +362,11 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
ep->currentExpression = q;
- if (sse.isValid()) {
+ // This object might be deleted during the eval
+ QmlExpressionData *localData = data;
+ localData->addref();
+
+ if (data->sse.isValid()) {
rv = evalSSE();
} else {
rv = evalQtScript(secondaryScope);
@@ -339,12 +374,17 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
ep->currentExpression = lastCurrentExpression;
- if ((!q->trackChange() || !ep->capturedProperties.count()) && guardList) {
- clearGuards();
- } else if(q->trackChange()) {
- updateGuards(ep->capturedProperties);
+ // Check if we were deleted
+ if (localData->q) {
+ if ((!data->trackChange || !ep->capturedProperties.count()) && data->guardList) {
+ clearGuards();
+ } else if(data->trackChange) {
+ updateGuards(ep->capturedProperties);
+ }
}
+ localData->release();
+
lastCapturedProperties.copyAndClear(ep->capturedProperties);
return rv;
@@ -368,7 +408,7 @@ QVariant QmlExpression::value()
bool QmlExpression::isConstant() const
{
Q_D(const QmlExpression);
- return !d->guardList;
+ return !d->data->guardList;
}
/*!
@@ -377,7 +417,7 @@ bool QmlExpression::isConstant() const
bool QmlExpression::trackChange() const
{
Q_D(const QmlExpression);
- return d->trackChange;
+ return d->data->trackChange;
}
/*!
@@ -398,7 +438,7 @@ bool QmlExpression::trackChange() const
void QmlExpression::setTrackChange(bool trackChange)
{
Q_D(QmlExpression);
- d->trackChange = trackChange;
+ d->data->trackChange = trackChange;
}
/*!
@@ -408,8 +448,8 @@ void QmlExpression::setTrackChange(bool trackChange)
void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
{
Q_D(QmlExpression);
- d->fileName = fileName.toString();
- d->line = line;
+ d->data->fileName = fileName.toString();
+ d->data->line = line;
}
/*!
@@ -421,7 +461,7 @@ void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
QObject *QmlExpression::scopeObject() const
{
Q_D(const QmlExpression);
- return d->me;
+ return d->data->me;
}
/*! \internal */
@@ -439,16 +479,16 @@ void QmlExpressionPrivate::clearGuards()
notifyIdx =
QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
- for (int ii = 0; ii < guardListLength; ++ii) {
- if (guardList[ii].data()) {
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ for (int ii = 0; ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data()) {
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
}
- delete [] guardList; guardList = 0;
- guardListLength = 0;
+ delete [] data->guardList; data->guardList = 0;
+ data->guardListLength = 0;
}
void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties)
@@ -461,10 +501,10 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
notifyIdx =
QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
- SignalGuard *newGuardList = 0;
+ QmlExpressionData::SignalGuard *newGuardList = 0;
- if (properties.count() != guardListLength)
- newGuardList = new SignalGuard[properties.count()];
+ if (properties.count() != data->guardListLength)
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
bool outputWarningHeader = false;
int hit = 0;
@@ -472,20 +512,20 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
const QmlEnginePrivate::CapturedProperty &property = properties.at(ii);
bool needGuard = true;
- if (ii >= guardListLength) {
+ if (ii >= data->guardListLength) {
// New guard
- } else if(guardList[ii].data() == property.object &&
- guardList[ii].notifyIndex == property.notifyIndex) {
+ } else if(data->guardList[ii].data() == property.object &&
+ data->guardList[ii].notifyIndex == property.notifyIndex) {
// Cache hit
- if (!guardList[ii].isDuplicate ||
- (guardList[ii].isDuplicate && hit == ii)) {
+ if (!data->guardList[ii].isDuplicate ||
+ (data->guardList[ii].isDuplicate && hit == ii)) {
needGuard = false;
++hit;
}
- } else if(guardList[ii].data() && !guardList[ii].isDuplicate) {
+ } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
// Cache miss
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
/* else {
@@ -494,9 +534,9 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
if (needGuard) {
if (!newGuardList) {
- newGuardList = new SignalGuard[properties.count()];
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
for (int jj = 0; jj < ii; ++jj)
- newGuardList[jj] = guardList[jj];
+ newGuardList[jj] = data->guardList[jj];
}
if (property.notifyIndex != -1) {
@@ -526,22 +566,22 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
<< "::" << metaProp.name();
}
} else if (newGuardList) {
- newGuardList[ii] = guardList[ii];
+ newGuardList[ii] = data->guardList[ii];
}
}
- for (int ii = properties.count(); ii < guardListLength; ++ii) {
- if (guardList[ii].data() && !guardList[ii].isDuplicate) {
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ for (int ii = properties.count(); ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
}
if (newGuardList) {
- if (guardList) delete [] guardList;
- guardList = newGuardList;
- guardListLength = properties.count();
+ if (data->guardList) delete [] data->guardList;
+ data->guardList = newGuardList;
+ data->guardListLength = properties.count();
}
}
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index 501e5d8..33016e6 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -79,23 +79,13 @@ private:
QmlAbstractExpression *m_nextExpression;
};
-class QmlExpression;
-class QString;
-class QmlExpressionPrivate : public QObjectPrivate, public QmlAbstractExpression
+class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount
{
- Q_DECLARE_PUBLIC(QmlExpression)
public:
- QmlExpressionPrivate();
- ~QmlExpressionPrivate();
-
- enum CompiledDataType {
- BasicScriptEngineData = 1,
- PreTransformedQtScriptData = 2
- };
+ QmlExpressionData();
+ ~QmlExpressionData();
-
- void init(QmlContext *, const QString &, QObject *);
- void init(QmlContext *, void *, QmlRefCount *, QObject *);
+ QmlExpressionPrivate *q;
QString expression;
bool expressionFunctionValid:1;
@@ -109,10 +99,6 @@ public:
QString fileName;
int line;
- QVariant value(QObject *secondaryScope = 0);
- QVariant evalSSE();
- QVariant evalQtScript(QObject *secondaryScope);
-
struct SignalGuard : public QGuard<QObject> {
SignalGuard() : isDuplicate(false), notifyIndex(-1) {}
@@ -132,6 +118,32 @@ public:
};
SignalGuard *guardList;
int guardListLength;
+};
+
+class QmlExpression;
+class QString;
+class QmlExpressionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlExpression)
+public:
+ QmlExpressionPrivate();
+ QmlExpressionPrivate(QmlExpressionData *);
+ ~QmlExpressionPrivate();
+
+ enum CompiledDataType {
+ BasicScriptEngineData = 1,
+ PreTransformedQtScriptData = 2
+ };
+
+ void init(QmlContext *, const QString &, QObject *);
+ void init(QmlContext *, void *, QmlRefCount *, QObject *);
+
+ QmlExpressionData *data;
+
+ QVariant value(QObject *secondaryScope = 0);
+ QVariant evalSSE();
+ QVariant evalQtScript(QObject *secondaryScope);
+
void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
void clearGuards();
diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp
new file mode 100644
index 0000000..0ade5ee
--- /dev/null
+++ b/src/declarative/qml/qmlglobalscriptclass.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 "qmlglobalscriptclass_p.h"
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Used to prevent any writes to the global object.
+*/
+QmlGlobalScriptClass::QmlGlobalScriptClass(QScriptEngine *engine)
+: QScriptClass(engine)
+{
+ QScriptValue v = engine->newObject();
+ globalObject = engine->globalObject();
+
+ QScriptValueIterator iter(globalObject);
+ while (iter.hasNext()) {
+ iter.next();
+ v.setProperty(iter.scriptName(), iter.value());
+ }
+
+ v.setScriptClass(this);
+ engine->setGlobalObject(v);
+}
+
+QScriptClass::QueryFlags
+QmlGlobalScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ return HandlesReadAccess | HandlesWriteAccess;
+}
+
+QScriptValue
+QmlGlobalScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ return engine()->undefinedValue();
+}
+
+void QmlGlobalScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id, const QScriptValue &value)
+{
+ QString error = QLatin1String("Invalid write to global property \"") +
+ name.toString() + QLatin1String("\"");
+ engine()->currentContext()->throwError(error);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/util/qmlscript.h b/src/declarative/qml/qmlglobalscriptclass_p.h
index 4ba4f6b..1b58f1e 100644
--- a/src/declarative/util/qmlscript.h
+++ b/src/declarative/qml/qmlglobalscriptclass_p.h
@@ -39,46 +39,43 @@
**
****************************************************************************/
-#ifndef QMLSCRIPT_H
-#define QMLSCRIPT_H
+#ifndef QMLGLOBALSCRIPTCLASS_P_H
+#define QMLGLOBALSCRIPTCLASS_P_H
-#include <QtDeclarative/qfxglobal.h>
-#include <QtCore/qobject.h>
-#include <QtDeclarative/qml.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.
+//
-QT_BEGIN_HEADER
+#include <QtScript/qscriptclass.h>
QT_BEGIN_NAMESPACE
-QT_MODULE(Declarative)
-
-class QmlScriptPrivate;
-class Q_DECLARATIVE_EXPORT QmlScript : public QObject
+class QmlGlobalScriptClass : public QScriptClass
{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QmlScript)
-
- Q_PROPERTY(QString script READ script WRITE setScript)
- Q_PROPERTY(QUrl source READ source WRITE setSource)
- Q_CLASSINFO("DefaultProperty", "script")
-
public:
- QmlScript(QObject *parent=0);
+ QmlGlobalScriptClass(QScriptEngine *);
- QString script() const;
- void setScript(const QString &);
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
- QUrl source() const;
- void setSource(const QUrl &);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint id);
-private Q_SLOTS:
- void replyFinished();
+ virtual void setProperty(QScriptValue &object, const QScriptString &name,
+ uint id, const QScriptValue &value);
+
+private:
+ QScriptValue globalObject;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QmlScript)
-
-QT_END_HEADER
-
-#endif
+#endif // QMLGLOBALSCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index b71c6e3..18439f4 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -69,7 +69,7 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx)
qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
break;
case QmlInstruction::StoreMetaObject:
- qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData;
+ qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t";
break;
case QmlInstruction::StoreFloat:
qWarning() << idx << "\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 2c9ceac..1dcdace 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -118,6 +118,7 @@ public:
StoreInterface, /* storeObject */
StoreSignal, /* storeSignal */
+ StoreScript, /* storeScript */
//
// Unresolved single assignment
@@ -165,7 +166,7 @@ public:
struct {
int bindingsSize;
int parserStatusSize;
- int idSize;
+ int contextCache;
} init;
struct {
int type;
@@ -175,8 +176,8 @@ public:
} create;
struct {
int data;
- int slotData;
int aliasData;
+ int propertyCache;
} storeMeta;
struct {
int value;
@@ -238,6 +239,9 @@ public:
int value;
} storeString;
struct {
+ int value;
+ } storeScript;
+ struct {
int propertyIndex;
int value;
} storeUrl;
diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp
new file mode 100644
index 0000000..564faaa
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 "qmlintegercache_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlIntegerCache::QmlIntegerCache(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlIntegerCache::~QmlIntegerCache()
+{
+ qDeleteAll(stringCache);
+}
+
+void QmlIntegerCache::add(const QString &id, int value)
+{
+ Q_ASSERT(!stringCache.contains(id));
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### use contextClass
+ Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value);
+
+ stringCache.insert(id, d);
+ identifierCache.insert(d->identifier, d);
+}
+
+int QmlIntegerCache::value(const QString &id)
+{
+ Data *d = stringCache.value(id);
+ return d?d->value:-1;
+}
+
+QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engine)
+{
+ Q_ASSERT(type);
+ Q_ASSERT(engine);
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ const QMetaObject *mo = type->metaObject();
+
+ for (int ii = mo->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum enumerator = mo->enumerator(ii);
+
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ QString name = QLatin1String(enumerator.key(jj));
+ int value = enumerator.value(jj);
+
+ if (!name.at(0).isUpper())
+ continue;
+
+ if (cache->stringCache.contains(name))
+ continue;
+
+ cache->add(name, value);
+ }
+ }
+
+ return cache;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h
new file mode 100644
index 0000000..e11e0be
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 QMLINTEGERCACHE_P_H
+#define QMLINTEGERCACHE_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 <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlIntegerCache : public QmlRefCount
+{
+public:
+ QmlIntegerCache(QmlEngine *);
+ virtual ~QmlIntegerCache();
+
+ inline int count() const;
+ void add(const QString &, int);
+ int value(const QString &);
+ inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+
+ static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *);
+private:
+ struct Data : public QScriptDeclarativeClass::PersistentIdentifier {
+ Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v)
+ : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {}
+
+ int value;
+ };
+
+ typedef QHash<QString, Data *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+int QmlIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+{
+ Data *d = identifierCache.value(id);
+ return d?d->value:-1;
+}
+
+int QmlIntegerCache::count() const
+{
+ return stringCache.count();
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLINTEGERCACHE_P_H
+
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index efc4a2b..302ce8c 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -58,56 +58,6 @@ Q_DECLARE_METATYPE(QList<QObject *>);
QT_BEGIN_NAMESPACE
-QmlMetaObjectCache::QmlMetaObjectCache()
-: propertyCache(0)
-{
-}
-
-void QmlMetaObjectCache::init(const QMetaObject *metaObject)
-{
- if (propertyCache || !metaObject)
- return;
-
- int propCount = metaObject->propertyCount();
-
- propertyCache = new Data[propCount];
- for (int ii = 0; ii < propCount; ++ii) {
- QMetaProperty p = metaObject->property(ii);
- propertyCache[ii].propType = p.userType();
- propertyCache[ii].coreIndex = ii;
- propertyCache[ii].name = QLatin1String(p.name());
-
- propertyNameCache.insert(propertyCache[ii].name, ii);
- }
-}
-
-QmlMetaObjectCache::~QmlMetaObjectCache()
-{
- delete [] propertyCache;
-}
-
-QmlMetaObjectCache::Data *
-QmlMetaObjectCache::property(int index, const QMetaObject *metaObject)
-{
- init(metaObject);
-
- return propertyCache + index;
-}
-
-QmlMetaObjectCache::Data *
-QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject)
-{
- init(metaObject);
-
- QHash<QString, int>::ConstIterator iter = propertyNameCache.find(name);
-
- if (iter != propertyNameCache.end()) {
- return propertyCache + *iter;
- } else {
- return 0;
- }
-}
-
/*!
\class QmlMetaProperty
\brief The QmlMetaProperty class abstracts accessing QML properties.
@@ -122,9 +72,7 @@ QmlMetaProperty::QmlMetaProperty()
d->q = this;
}
-/*!
- The destructor deletes its heap data.
- */
+/*! \internal */
QmlMetaProperty::~QmlMetaProperty()
{
delete d; d = 0;
@@ -164,11 +112,9 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
object = obj;
QMetaProperty p = QmlMetaType::defaultProperty(obj);
- name = QLatin1String(p.name());
- propType = p.userType();;
- coreIdx = p.propertyIndex();
- if (!name.isEmpty())
- type = QmlMetaProperty::Property | QmlMetaProperty::Default;
+ core.load(p);
+ if (core.isValid())
+ isDefaultProperty = true;
}
/*!
@@ -179,15 +125,12 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt)
: d(new QmlMetaPropertyPrivate)
{
+ Q_ASSERT(obj);
+
d->q = this;
d->context = ctxt;
d->object = obj;
- d->type = Property;
- QMetaProperty p = obj->metaObject()->property(idx);
- d->propType = p.userType();
- d->coreIdx = idx;
- if (p.name() != 0)
- d->name = QLatin1String(p.name());
+ d->core.load(obj->metaObject()->property(idx));
}
/*!
@@ -218,7 +161,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (context && context->engine())
enginePrivate = QmlEnginePrivate::get(context->engine());
- this->name = name;
object = obj;
if (name.isEmpty() || !obj)
@@ -235,8 +177,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0);
if (t && t->attachedPropertiesFunction()) {
attachedFunc = t->index();
- if (attachedFunc != -1)
- type = QmlMetaProperty::Property | QmlMetaProperty::Attached;
}
typeData->release();
}
@@ -250,30 +190,31 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
QString signalName = name.mid(2);
signalName[0] = signalName.at(0).toLower();
- findSignalInt(obj, signalName);
- if (signal.signature() != 0) {
- type = QmlMetaProperty::SignalProperty;
+ QMetaMethod method = findSignal(obj, signalName);
+ if (method.signature()) {
+ core.load(method);
return;
}
}
// Property
- QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj);
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache)
+ cache = enginePrivate?enginePrivate->cache(obj):0;
+
if (cache) {
- QmlMetaObjectCache::Data *data =
- cache->property(name, obj->metaObject());
- if (data) {
- type = QmlMetaProperty::Property;
- propType = data->propType;
- coreIdx = data->coreIndex;
- }
+ QmlPropertyCache::Data *data = cache->property(name);
+
+ if (data && !(data->flags & QmlPropertyCache::Data::IsFunction))
+ core = *data;
+
} else {
- // Can't cache
+ // No cache available
QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData());
- propType = p.userType();
- coreIdx = p.propertyIndex();
- if (p.name())
- type = QmlMetaProperty::Property;
+ core.load(p);
}
}
@@ -323,33 +264,31 @@ QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
QmlMetaProperty::PropertyCategory
QmlMetaPropertyPrivate::propertyCategory() const
{
- if (category == QmlMetaProperty::Unknown) {
+ uint type = q->type();
+
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return QmlMetaProperty::Normal;
+ } else if (type & QmlMetaProperty::Attached) {
+ return QmlMetaProperty::Object;
+ } else if (type & QmlMetaProperty::Property) {
int type = propertyType();
- if (type == QmlMetaProperty::Invalid)
- category = QmlMetaProperty::InvalidProperty;
- else if (type < QVariant::UserType)
- category = QmlMetaProperty::Normal;
+ if (type == QVariant::Invalid)
+ return QmlMetaProperty::InvalidProperty;
+ else if ((uint)type < QVariant::UserType)
+ return QmlMetaProperty::Normal;
else if (type == qMetaTypeId<QmlBinding *>())
- category = QmlMetaProperty::Bindable;
- else {
- QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type);
- switch(tc) {
- case QmlMetaType::Object:
- category = QmlMetaProperty::Object;
- break;
- case QmlMetaType::QmlList:
- category = QmlMetaProperty::QmlList;
- break;
- case QmlMetaType::List:
- category = QmlMetaProperty::List;
- break;
- case QmlMetaType::Unknown:
- category = QmlMetaProperty::Normal;
- break;
- }
- }
+ return QmlMetaProperty::Bindable;
+ else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived)
+ return QmlMetaProperty::Object;
+ else if (core.flags & QmlPropertyCache::Data::IsQmlList)
+ return QmlMetaProperty::QmlList;
+ else if (core.flags & QmlPropertyCache::Data::IsQList)
+ return QmlMetaProperty::List;
+ else
+ return QmlMetaProperty::Normal;
+ } else {
+ return QmlMetaProperty::InvalidProperty;
}
- return category;
}
/*!
@@ -358,8 +297,21 @@ QmlMetaPropertyPrivate::propertyCategory() const
*/
const char *QmlMetaProperty::propertyTypeName() const
{
- if (!d->name.isEmpty() && d->object) {
- return d->object->metaObject()->property(d->coreIdx).typeName();
+ if (type() & ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ const char *rv = valueType->metaObject()->property(d->valueTypeCoreIdx).typeName();
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else if (d->object && type() & Property && d->core.isValid()) {
+ return d->object->metaObject()->property(d->core.coreIndex).typeName();
} else {
return 0;
}
@@ -371,10 +323,13 @@ const char *QmlMetaProperty::propertyTypeName() const
*/
bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
{
- return d->name == other.d->name &&
- d->signal.signature() == other.d->signal.signature() &&
- d->type == other.d->type &&
- d->object == other.d->object;
+ // category is intentially omitted here as it is generated
+ // from the other members
+ return d->object == other.d->object &&
+ d->core == other.d->core &&
+ d->valueTypeCoreIdx == other.d->valueTypeCoreIdx &&
+ d->valueTypePropType == other.d->valueTypePropType &&
+ d->attachedFunc == other.d->attachedFunc;
}
/*!
@@ -388,18 +343,19 @@ int QmlMetaProperty::propertyType() const
int QmlMetaPropertyPrivate::propertyType() const
{
- int rv = QVariant::Invalid;
-
- if (!name.isEmpty()) {
- if (propType == (int)QVariant::LastType)
- rv = qMetaTypeId<QVariant>();
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return valueTypePropType;
+ } else if (type & QmlMetaProperty::Attached) {
+ return qMetaTypeId<QObject *>();
+ } else if (type & QmlMetaProperty::Property) {
+ if (core.propType == (int)QVariant::LastType)
+ return qMetaTypeId<QVariant>();
else
- rv = propType;
- } else if (attachedFunc) {
- rv = qMetaTypeId<QObject *>();
- }
-
- return rv;
+ return core.propType;
+ } else {
+ return QVariant::Invalid;
+ }
}
/*!
@@ -407,7 +363,16 @@ int QmlMetaPropertyPrivate::propertyType() const
*/
QmlMetaProperty::Type QmlMetaProperty::type() const
{
- return (Type)d->type;
+ if (d->core.flags & QmlPropertyCache::Data::IsFunction)
+ return SignalProperty;
+ else if (d->attachedFunc != -1)
+ return Attached;
+ else if (d->valueTypeCoreIdx != -1)
+ return (Type)(Property | ValueTypeProperty);
+ else if (d->core.isValid())
+ return (Type)(Property | ((d->isDefaultProperty)?Default:0));
+ else
+ return Invalid;
}
/*!
@@ -439,17 +404,16 @@ QObject *QmlMetaProperty::object() const
*/
QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
{
- d->name = other.d->name;
- d->signal = other.d->signal;
d->context = other.d->context;
- d->coreIdx = other.d->coreIdx;
- d->valueTypeIdx = other.d->valueTypeIdx;
- d->valueTypeId = other.d->valueTypeId;
- d->type = other.d->type;
- d->attachedFunc = other.d->attachedFunc;
d->object = other.d->object;
- d->propType = other.d->propType;
- d->category = other.d->category;
+
+ d->isDefaultProperty = other.d->isDefaultProperty;
+ d->core = other.d->core;
+
+ d->valueTypeCoreIdx = other.d->valueTypeCoreIdx;
+ d->valueTypePropType = other.d->valueTypePropType;
+
+ d->attachedFunc = other.d->attachedFunc;
return *this;
}
@@ -458,12 +422,14 @@ QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
*/
bool QmlMetaProperty::isWritable() const
{
- if (propertyCategory() == List || propertyCategory() == QmlList)
+ QmlMetaProperty::PropertyCategory category = propertyCategory();
+
+ if (category == List || category == QmlList)
return true;
else if (type() & SignalProperty)
return true;
- else if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isWritable();
+ else if (d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isWritable();
else
return false;
}
@@ -473,8 +439,8 @@ bool QmlMetaProperty::isWritable() const
*/
bool QmlMetaProperty::isDesignable() const
{
- if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isDesignable();
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
else
return false;
}
@@ -493,6 +459,7 @@ bool QmlMetaProperty::isValid() const
*/
QStringList QmlMetaProperty::properties(QObject *obj)
{
+ // ### What is this used for?
if (!obj)
return QStringList();
@@ -511,7 +478,23 @@ QStringList QmlMetaProperty::properties(QObject *obj)
*/
QString QmlMetaProperty::name() const
{
- return d->name;
+ if (type() & ValueTypeProperty) {
+ QString rv = d->core.name + QLatin1String(".");
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name());
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else {
+ return d->core.name;
+ }
}
/*!
@@ -520,13 +503,26 @@ QString QmlMetaProperty::name() const
*/
QMetaProperty QmlMetaProperty::property() const
{
- if (d->object)
- return d->object->metaObject()->property(d->coreIdx);
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex);
else
return QMetaProperty();
}
/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ if (type() & SignalProperty && d->object)
+ return d->object->metaObject()->method(d->core.coreIndex);
+ else
+ return QMetaMethod();
+}
+
+
+/*!
Returns the binding associated with this property, or 0 if no binding
exists.
*/
@@ -539,13 +535,13 @@ QmlAbstractBinding *QmlMetaProperty::binding() const
if (!data)
return 0;
- if (!data->hasBindingBit(d->coreIdx))
+ if (!data->hasBindingBit(d->core.coreIndex))
return 0;
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx)
+ if (binding->propertyIndex() == d->core.coreIndex)
return binding;
binding = binding->m_nextBinding;
}
@@ -568,14 +564,20 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
if (!isProperty() || (type() & Attached) || !d->object)
return 0;
- QmlDeclarativeData *data =
- QmlDeclarativeData::get(d->object, 0 != newBinding);
+ return d->setBinding(d->object, d->core, newBinding);
+}
+
+QmlAbstractBinding *
+QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core,
+ QmlAbstractBinding *newBinding)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding);
- if (data && data->hasBindingBit(d->coreIdx)) {
+ if (data && data->hasBindingBit(core.coreIndex)) {
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx) {
+ if (binding->propertyIndex() == core.coreIndex) {
binding->setEnabled(false);
if (newBinding)
@@ -638,15 +640,14 @@ QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
}
if (expr) {
- QmlBoundSignal *signal = new QmlBoundSignal(d->object, d->signal,
- d->object);
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object);
return signal->setExpression(expr);
} else {
return 0;
}
}
-void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
{
const QMetaObject *mo = obj->metaObject();
@@ -657,12 +658,10 @@ void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
int idx = methodName.indexOf(QLatin1Char('('));
methodName = methodName.left(idx);
- if (methodName == name) {
- signal = method;
- coreIdx = ii;
- return;
- }
+ if (methodName == name)
+ return method;
}
+ return QMetaMethod();
}
QObject *QmlMetaPropertyPrivate::attachedObject() const
@@ -687,31 +686,14 @@ QVariant QmlMetaProperty::read() const
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == d->coreIdx)
+ if (sig && sig->index() == d->core.coreIndex)
return sig->expression()->expression();
}
+
} else if (type() & Property) {
- if (type() & Attached) {
- return QVariant::fromValue(d->attachedObject());
- } else if(type() & ValueTypeProperty) {
- QmlEnginePrivate *ep = d->context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(d->context->engine())):0;
- QmlValueType *valueType = 0;
- if (ep)
- valueType = ep->valueTypes[d->valueTypeId];
- else
- valueType = QmlValueTypeFactory::valueType(d->valueTypeId);
- Q_ASSERT(valueType);
-
- valueType->read(object(), d->coreIdx);
- QVariant rv =
- valueType->metaObject()->property(d->valueTypeIdx).read(valueType);
- if (!ep)
- delete valueType;
- return rv;
- } else {
- return d->object->metaObject()->property(d->coreIdx).read(object());
- }
+ return d->readValueProperty();
+
}
return QVariant();
}
@@ -723,7 +705,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == coreIdx) {
+ if (sig && sig->index() == core.coreIndex) {
if (expr.isEmpty()) {
sig->disconnect();
sig->deleteLater();
@@ -736,47 +718,86 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
if (!expr.isEmpty()) {
// XXX scope
- (void *)new QmlBoundSignal(qmlContext(object), expr, object, signal, object);
+ (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object);
+ }
+}
+
+QVariant QmlMetaPropertyPrivate::readValueProperty()
+{
+ uint type = q->type();
+ if (type & QmlMetaProperty::Attached) {
+
+ return QVariant::fromValue(attachedObject());
+
+ } else if(type & QmlMetaProperty::ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[core.propType];
+ else valueType = QmlValueTypeFactory::valueType(core.propType);
+ Q_ASSERT(valueType);
+
+ valueType->read(object, core.coreIndex);
+
+ QVariant rv =
+ valueType->metaObject()->property(valueTypeCoreIdx).read(valueType);
+
+ if (!ep) delete valueType;
+ return rv;
+
+ } else {
+
+ return object->metaObject()->property(core.coreIndex).read(object.data());
+
}
}
void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaProperty::WriteSource source)
{
- QObject *object = this->object;
- int coreIdx = this->coreIdx;
-
- QmlValueType *writeBack = 0;
- QObject *writeBackObj = 0;
- int writeBackIdx = -1;
- bool deleteWriteBack = false;
-
// Remove any existing bindings on this property
if (source != QmlMetaProperty::Binding)
delete q->setBinding(0);
+ uint type = q->type();
if (type & QmlMetaProperty::ValueTypeProperty) {
- QmlEnginePrivate *ep = context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlEnginePrivate *ep =
+ context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlValueType *writeBack = 0;
if (ep) {
- writeBack = ep->valueTypes[valueTypeId];
+ writeBack = ep->valueTypes[core.propType];
} else {
- writeBack = QmlValueTypeFactory::valueType(valueTypeId);
- deleteWriteBack = true;
+ writeBack = QmlValueTypeFactory::valueType(core.propType);
}
- writeBackObj = this->object;
- writeBackIdx = this->coreIdx;
- writeBack->read(writeBackObj, writeBackIdx);
- object = writeBack;
- coreIdx = valueTypeIdx;
+ writeBack->read(object, core.coreIndex);
+
+ QmlPropertyCache::Data data = core;
+ data.coreIndex = valueTypeCoreIdx;
+ data.propType = valueTypePropType;
+ write(writeBack, data, value, context);
+
+ writeBack->write(object, core.coreIndex);
+ if (!ep) delete writeBack;
+
+ } else {
+
+ write(object, core, value, context);
+
}
+}
- QMetaProperty prop = object->metaObject()->property(coreIdx);
+void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
+ const QVariant &value, QmlContext *context)
+{
+ int coreIdx = property.coreIndex;
- if (prop.isEnumType()) {
+ if (property.flags & QmlPropertyCache::Data::IsEnumType) {
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant v = value;
- if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ // Enum values come through the script engine as doubles
+ if (value.type() == QVariant::Double) {
double integral;
double fractional = modf(value.toDouble(), &integral);
if (qFuzzyCompare(fractional, (double)0.0))
@@ -784,19 +805,36 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
prop.write(object, v);
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
- }
return;
}
- int t = propertyType();
+ int t = property.propType;
int vt = value.userType();
- int category = propertyCategory();
- if (vt == t
- && t != QVariant::Url) { // always resolve relative urls
+ if (t == QVariant::Url) {
+
+ QUrl u;
+ bool found = false;
+ if (vt == QVariant::Url) {
+ u = value.toUrl();
+ found = true;
+ } else if (vt == QVariant::ByteArray) {
+ u = QUrl(QLatin1String(value.toByteArray()));
+ found = true;
+ } else if (vt == QVariant::String) {
+ u = QUrl(value.toString());
+ found = true;
+ }
+
+ 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);
+ }
+
+ } else if (vt == t) {
void *a[1];
a[0] = (void *)value.constData();
@@ -804,9 +842,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
} else if (qMetaTypeId<QVariant>() == t) {
- prop.write(object, value);
+ void *a[1];
+ a[0] = (void *)&value;
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
- } else if (category == QmlMetaProperty::Object) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
QObject *o = QmlMetaType::toQObject(value);
@@ -833,9 +873,10 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
- } else if (category == QmlMetaProperty::List) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQList) {
int listType = QmlMetaType::listType(t);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
const QList<QObject *> &list =
@@ -853,9 +894,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaType::clear(listVar);
QmlMetaType::append(listVar, value);
}
- } else if (category == QmlMetaProperty::QmlList) {
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQmlList) {
// XXX - optimize!
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant list = prop.read(object);
QmlPrivate::ListInterface *li =
*(QmlPrivate::ListInterface **)list.constData();
@@ -885,118 +928,25 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
void *d = (void *)&obj;
li->append(d);
}
- } else if (category == QmlMetaProperty::Normal) {
-
- bool found = false;
- switch(t) {
- case QVariant::Double:
- {
- double d;
- if (vt == QVariant::Int) {
- d = value.toInt();
- found = true;
- } else if (vt == QVariant::UInt) {
- d = value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &d;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Int:
- {
- int i;
- if (vt == QVariant::Double) {
- i = (int)value.toDouble();
- found = true;
- } else if (vt == QVariant::UInt) {
- i = (int)value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &i;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::String:
- {
- QString s;
- if (vt == QVariant::ByteArray) {
- s = QLatin1String(value.toByteArray());
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &s;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Url:
- {
- QUrl u;
- if (vt == QVariant::Url) {
- u = value.toUrl();
- found = true;
- } else if (vt == QVariant::ByteArray) {
- u = QUrl(QLatin1String(value.toByteArray()));
- found = true;
- } else if (vt == QVariant::String) {
- u = QUrl(value.toString());
- found = true;
- }
+ } else {
+ Q_ASSERT(vt != t);
- if (found) {
- if (context && u.isRelative() && !u.isEmpty())
- u = context->baseUrl().resolved(u);
+ QVariant v = value;
+ if (v.convert((QVariant::Type)t)) {
+ void *a[1];
+ a[0] = (void *)v.constData();
+ 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] = &u;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
-
- }
- break;
-
-
- default:
- {
- if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
- QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
- if (con) {
- QVariant v = con(value.toString());
- prop.write(object, v);
- found = true;
- }
+ a[0] = (void *)v.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
}
}
- break;
}
- if (!found)
- prop.write(object, value);
- }
-
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
}
}
@@ -1017,7 +967,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
d->writeSignalProperty(value);
- } else if (d->coreIdx != -1) {
+ } else if (d->core.isValid()) {
d->writeValueProperty(value, source);
@@ -1030,7 +980,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
bool QmlMetaProperty::hasChangedNotifier() const
{
if (type() & Property && !(type() & Attached) && d->object) {
- return d->object->metaObject()->property(d->coreIdx).hasNotifySignal();
+ return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
}
return false;
}
@@ -1061,7 +1011,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
} else {
@@ -1082,7 +1032,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
return QObject::connect(d->object, signal.constData(), dest, slot);
@@ -1096,7 +1046,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
*/
int QmlMetaProperty::coreIndex() const
{
- return d->coreIdx;
+ return d->core.coreIndex;
}
Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes);
@@ -1111,17 +1061,17 @@ quint32 QmlMetaProperty::save() const
if (type() & Attached) {
rv = d->attachedFunc;
} else if (type() != Invalid) {
- rv = d->coreIdx;
+ rv = d->core.coreIndex;
}
Q_ASSERT(rv <= 0x7FF);
Q_ASSERT(type() <= 0x3F);
- Q_ASSERT(d->valueTypeIdx <= 0x7F);
+ Q_ASSERT(d->valueTypeCoreIdx <= 0x7F);
rv |= (type() << 18);
if (type() & ValueTypeProperty)
- rv |= (d->valueTypeIdx << 11);
+ rv |= (d->valueTypeCoreIdx << 11);
return rv;
}
@@ -1162,12 +1112,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
d->context = ctxt;
id &= 0xFFFFFF;
- d->type = id >> 18;
+ uint type = id >> 18;
id &= 0xFFFF;
- if (d->type & Attached) {
+ if (type & Attached) {
d->attachedFunc = id;
- } else if (d->type & ValueTypeProperty) {
+ } else if (type & ValueTypeProperty) {
int coreIdx = id & 0x7FF;
int valueTypeIdx = id >> 11;
@@ -1178,47 +1128,31 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx));
- d->name = QLatin1String(p2.name());
- d->propType = p2.userType();
- d->coreIdx = coreIdx;
- d->valueTypeIdx = valueTypeIdx;
- d->valueTypeId = p.type();
-
- } else if (d->type & Property) {
+ d->core.load(p);
+ d->valueTypeCoreIdx = valueTypeIdx;
+ d->valueTypePropType = p2.userType();
+ } else if (type & Property) {
- QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj);
-
- d->coreIdx = id;
+ QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0;
if (cache) {
- QmlMetaObjectCache::Data *data =
- cache->property(id, obj->metaObject());
- d->propType = data->propType;
- d->name = data->name;
+ QmlPropertyCache::Data *data = cache->property(id);
+ if (data) d->core = *data;
} else {
QMetaProperty p(obj->metaObject()->property(id));
- d->name = QLatin1String(p.name());
- d->propType = p.userType();
+ d->core.load(p);
}
- } else if (d->type & SignalProperty) {
- d->signal = obj->metaObject()->method(id);
- d->coreIdx = id;
+ } else if (type & SignalProperty) {
+
+ QMetaMethod method = obj->metaObject()->method(id);
+ d->core.load(method);
} else {
*this = QmlMetaProperty();
}
}
/*!
- Return the QMetaMethod for this property if it is a SignalProperty,
- otherwise returns an invalid QMetaMethod.
-*/
-QMetaMethod QmlMetaProperty::method() const
-{
- return d->signal;
-}
-
-/*!
\internal
Creates a QmlMetaProperty for the property \a name of \a obj. Unlike
@@ -1245,17 +1179,11 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj,
int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
if (idx == -1)
return QmlMetaProperty();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
- QmlMetaProperty p;
- p.d->name = pathName + QLatin1String(".") + path.last();
- p.d->context = 0;
- p.d->coreIdx = prop.coreIndex();
- p.d->valueTypeIdx = idx;
- p.d->valueTypeId = prop.propertyType();
- p.d->type = QmlMetaProperty::ValueTypeProperty |
- QmlMetaProperty::Property;
- p.d->object = obj;
- p.d->propType = typeObject->metaObject()->property(idx).userType();
+ QmlMetaProperty p = prop;
+ p.d->valueTypeCoreIdx = idx;
+ p.d->valueTypePropType = vtProp.userType();
return p;
}
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
index 1ccf913..00b9c3a 100644
--- a/src/declarative/qml/qmlmetaproperty_p.h
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -54,73 +54,54 @@
//
#include "qmlmetaproperty.h"
-#include "private/qobject_p.h"
+#include <private/qobject_p.h>
+#include <private/qmlpropertycache_p.h>
QT_BEGIN_NAMESPACE
-class QmlMetaObjectCache
-{
-public:
- QmlMetaObjectCache();
- ~QmlMetaObjectCache();
-
- struct Data {
- int propType;
- int coreIndex;
- QString name;
- };
-
- Data *property(const QString &, const QMetaObject *);
- Data *property(int, const QMetaObject *);
-
-private:
- void init(const QMetaObject *);
-
- Data *propertyCache;
- QHash<QString, int> propertyNameCache;
-};
-
class QmlContext;
class QmlMetaPropertyPrivate
{
public:
QmlMetaPropertyPrivate()
- : q(0), context(0), coreIdx(-1), valueTypeIdx(-1), valueTypeId(0),
- type(QmlMetaProperty::Invalid), attachedFunc(-1),
- object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ : q(0), context(0), object(0), isDefaultProperty(false), valueTypeCoreIdx(-1),
+ valueTypePropType(0), attachedFunc(-1) {}
+
QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
- : q(0), name(other.name), signal(other.signal), context(other.context),
- coreIdx(other.coreIdx), valueTypeIdx(other.valueTypeIdx),
- valueTypeId(other.valueTypeId), type(other.type),
- attachedFunc(other.attachedFunc), object(other.object),
- propType(other.propType), category(other.category) {}
+ : q(0), context(other.context), object(other.object),
+ isDefaultProperty(other.isDefaultProperty), core(other.core),
+ valueTypeCoreIdx(other.valueTypeCoreIdx),
+ valueTypePropType(other.valueTypePropType), attachedFunc(other.attachedFunc) {}
QmlMetaProperty *q;
-
- QString name;
- QMetaMethod signal;
QmlContext *context;
- int coreIdx;
- int valueTypeIdx;
- int valueTypeId;
- uint type;
- int attachedFunc;
QGuard<QObject> object;
- int propType;
- mutable QmlMetaProperty::PropertyCategory category;
+ bool isDefaultProperty;
+ QmlPropertyCache::Data core;
+
+ // Describes the "virtual" value-type sub-property.
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+
+ // The attached property accessor
+ int attachedFunc;
void initProperty(QObject *obj, const QString &name);
void initDefault(QObject *obj);
QObject *attachedObject() const;
- void findSignalInt(QObject *, const QString &);
+ QMetaMethod findSignal(QObject *, const QString &);
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 *);
+ static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *);
static quint32 saveValueType(int, int);
static quint32 saveProperty(int);
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
index 14d85ff..c40232f 100644
--- a/src/declarative/qml/qmlmetatype.cpp
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -929,6 +929,30 @@ QList<QmlType*> QmlMetaType::qmlTypes()
return data->nameToType.values();
}
+#include <QtGui/qfont.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qpolygon.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtGui/qkeysequence.h>
+#include <QtGui/qpen.h>
+//#include <QtGui/qtextlength.h>
+#include <QtGui/qtextformat.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+
/*!
Copies \a copy into \a data, assuming they both are of type \a type. If
\a copy is zero, a default type is copied. Returns true if the copy was
@@ -988,7 +1012,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QVariantMap:
*static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
return true;
@@ -998,7 +1021,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVariantList:
*static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
return true;
-#endif
case QMetaType::QByteArray:
*static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
return true;
@@ -1008,11 +1030,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QStringList:
*static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QBitArray:
*static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
return true;
-#endif
case QMetaType::QDate:
*static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
return true;
@@ -1022,15 +1042,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QDateTime:
*static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
*static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
return true;
-#endif
case QMetaType::QLocale:
*static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
return true;
-#ifndef QT_NO_GEOM_VARIANT
case QMetaType::QRect:
*static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
return true;
@@ -1058,7 +1075,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVector3D:
*static_cast<NS(QVector3D) *>(data) = *static_cast<const NS(QVector3D)*>(copy);
return true;
-#endif
#ifndef QT_NO_REGEXP
case QMetaType::QRegExp:
*static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
@@ -1066,8 +1082,90 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
#endif
case QMetaType::Void:
return true;
+
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = *static_cast<const NS(QColorGroup)*>(copy);
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = *static_cast<const NS(QFont)*>(copy);
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = *static_cast<const NS(QPixmap)*>(copy);
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = *static_cast<const NS(QBrush)*>(copy);
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = *static_cast<const NS(QColor)*>(copy);
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = *static_cast<const NS(QPalette)*>(copy);
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = *static_cast<const NS(QIcon)*>(copy);
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = *static_cast<const NS(QImage)*>(copy);
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = *static_cast<const NS(QPolygon)*>(copy);
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = *static_cast<const NS(QRegion)*>(copy);
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = *static_cast<const NS(QBitmap)*>(copy);
+ return true;
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = *static_cast<const NS(QCursor)*>(copy);
+ return true;
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = *static_cast<const NS(QSizePolicy)*>(copy);
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = *static_cast<const NS(QKeySequence)*>(copy);
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = *static_cast<const NS(QPen)*>(copy);
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = *static_cast<const NS(QTextLength)*>(copy);
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = *static_cast<const NS(QTextFormat)*>(copy);
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = *static_cast<const NS(QMatrix)*>(copy);
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = *static_cast<const NS(QTransform)*>(copy);
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = *static_cast<const NS(QMatrix4x4)*>(copy);
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = *static_cast<const NS(QVector2D)*>(copy);
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = *static_cast<const NS(QVector4D)*>(copy);
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = *static_cast<const NS(QQuaternion)*>(copy);
+ return true;
+
default:
- ;
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = *static_cast<const NS(QVariant)*>(copy);
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ }
+ break;
}
} else {
switch(type) {
@@ -1118,7 +1216,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = NS(QChar)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QVariantMap:
*static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
return true;
@@ -1128,7 +1225,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVariantList:
*static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
return true;
-#endif
case QMetaType::QByteArray:
*static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
return true;
@@ -1138,11 +1234,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QStringList:
*static_cast<NS(QStringList) *>(data) = NS(QStringList)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QBitArray:
*static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
return true;
-#endif
case QMetaType::QDate:
*static_cast<NS(QDate) *>(data) = NS(QDate)();
return true;
@@ -1152,15 +1246,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QDateTime:
*static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
*static_cast<NS(QUrl) *>(data) = NS(QUrl)();
return true;
-#endif
case QMetaType::QLocale:
*static_cast<NS(QLocale) *>(data) = NS(QLocale)();
return true;
-#ifndef QT_NO_GEOM_VARIANT
case QMetaType::QRect:
*static_cast<NS(QRect) *>(data) = NS(QRect)();
return true;
@@ -1188,7 +1279,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVector3D:
*static_cast<NS(QVector3D) *>(data) = NS(QVector3D)();
return true;
-#endif
#ifndef QT_NO_REGEXP
case QMetaType::QRegExp:
*static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
@@ -1196,8 +1286,88 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
#endif
case QMetaType::Void:
return true;
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = NS(QColorGroup)();
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = NS(QFont)();
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = NS(QPixmap)();
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = NS(QBrush)();
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = NS(QColor)();
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = NS(QPalette)();
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = NS(QIcon)();
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = NS(QImage)();
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = NS(QPolygon)();
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = NS(QRegion)();
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = NS(QBitmap)();
+ return true;
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = NS(QCursor)();
+ return true;
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = NS(QSizePolicy)();
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = NS(QKeySequence)();
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = NS(QPen)();
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = NS(QTextLength)();
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = NS(QTextFormat)();
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = NS(QMatrix)();
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = NS(QTransform)();
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = NS(QMatrix4x4)();
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = NS(QVector2D)();
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = NS(QVector4D)();
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = NS(QQuaternion)();
+ return true;
default:
- ;
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = NS(QVariant)();
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = 0;
+ return true;
+ }
+ break;
}
}
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
new file mode 100644
index 0000000..41573a2
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** 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 "qmlobjectscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qguard_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <private/qmltypenamescriptclass_p.h>
+#include <QtDeclarative/qmlbinding.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ObjectData : public QScriptDeclarativeClass::Object {
+ ObjectData(QObject *o) : object(o) {}
+ QGuard<QObject> object;
+};
+
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript. It is also used to provide a more useful API in
+ QtScript for QML.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0),
+ engine(bindEngine)
+{
+ engine = bindEngine;
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
+
+ m_destroy = scriptEngine->newFunction(destroy);
+ m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
+ m_toString = scriptEngine->newFunction(tostring);
+ m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptValue QmlObjectScriptClass::newQObject(QObject *object)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object)
+ return newObject(scriptEngine, this, new ObjectData(object));
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true);
+
+ if (!ddata->scriptValue.isValid()) {
+ ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object));
+ return ddata->scriptValue;
+ } else if (ddata->scriptValue.engine() == QmlEnginePrivate::getScriptEngine(engine)) {
+ return ddata->scriptValue;
+ } else {
+ return newObject(scriptEngine, this, new ObjectData(object));
+ }
+}
+
+QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const
+{
+ return value.toQObject();
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ return queryProperty(toQObject(object), name, flags, 0);
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags, QmlContext *evalContext)
+{
+ Q_UNUSED(flags);
+ lastData = 0;
+ lastTNData = 0;
+
+ if (name == m_destroyId.identifier ||
+ name == m_toStringId.identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ if (!obj)
+ return 0;
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (cache) {
+ lastData = cache->property(name);
+ } else {
+ local = QmlPropertyCache::create(obj->metaObject(), toString(name));
+ if (local.isValid())
+ lastData = &local;
+ }
+
+ if (lastData) {
+ QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess;
+ if (lastData->flags & QmlPropertyCache::Data::IsWritable)
+ rv |= QScriptClass::HandlesWriteAccess;
+ return rv;
+ }
+
+ if (!evalContext && context()) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context(), -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
+
+ evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
+ }
+
+ if (evalContext) {
+ QmlContextPrivate *cp = QmlContextPrivate::get(evalContext);
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+ if (data) {
+ lastTNData = data;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name)
+{
+ return property(toQObject(object), name);
+}
+
+QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
+{
+ if (name == m_destroyId.identifier)
+ return m_destroy;
+ else if (name == m_toStringId.identifier)
+ return m_toString;
+
+ Q_ASSERT(obj);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (lastTNData) {
+
+ if (lastTNData->type)
+ return enginePriv->typeNameClass->newObject(obj, lastTNData->type);
+ else
+ return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace);
+
+ } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) {
+ // ### Optimize
+ QScriptValue sobj = scriptEngine->newQObject(obj);
+ return sobj.property(toString(name));
+ } else {
+ if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
+ enginePriv->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
+ }
+
+ if ((uint)lastData->propType < QVariant::UserType) {
+ QmlValueType *valueType = enginePriv->valueTypes[lastData->propType];
+ if (valueType)
+ return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType);
+ }
+
+ if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return newQObject(rv);
+ } else {
+ QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
+ return enginePriv->scriptValueFromVariant(var);
+ }
+
+ }
+}
+
+void QmlObjectScriptClass::setProperty(Object *object,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ return setProperty(toQObject(object), name, value);
+}
+
+void QmlObjectScriptClass::setProperty(QObject *obj,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+ Q_ASSERT(obj);
+ Q_ASSERT(lastData);
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### Can well known types be optimized?
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ delete QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0);
+ QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context());
+}
+
+QObject *QmlObjectScriptClass::toQObject(Object *object, bool *ok)
+{
+ if (ok) *ok = true;
+
+ ObjectData *data = (ObjectData*)object;
+ return data->object.data();
+}
+
+QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
+{
+ QObject* obj = context->thisObject().toQObject();
+
+ QString ret;
+ if(obj){
+ QString objectName = obj->objectName();
+
+ ret += QLatin1String(obj->metaObject()->className());
+ ret += QLatin1String("(0x");
+ ret += QString::number((quintptr)obj,16);
+
+ if (!objectName.isEmpty()) {
+ ret += QLatin1String(", \"");
+ ret += objectName;
+ ret += QLatin1String("\"");
+ }
+
+ ret += QLatin1String(")");
+ }else{
+ ret += QLatin1String("null");
+ }
+ return QScriptValue(ret);
+}
+
+QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
+{
+ QObject* obj = context->thisObject().toQObject();
+ if(obj){
+ int delay = 0;
+ if(context->argumentCount() > 0)
+ delay = context->argument(0).toInt32();
+ if (delay > 0)
+ QTimer::singleShot(delay, obj, SLOT(deleteLater()));
+ else
+ obj->deleteLater();
+ }
+ return engine->nullValue();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
new file mode 100644
index 0000000..3fcf009
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 QMLOBJECTSCRIPTCLASS_P_H
+#define QMLOBJECTSCRIPTCLASS_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 <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QScriptContext;
+class QScriptEngine;
+class QmlContext;
+class QmlObjectScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ QScriptValue newQObject(QObject *);
+ QObject *toQObject(const QScriptValue &) const;
+
+ enum QueryMode { IncludeAttachedProperties, SkipAttachedProperties };
+
+ QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
+ QScriptClass::QueryFlags flags,
+ QmlContext *evalContext);
+ QScriptValue property(QObject *, const Identifier &);
+ void setProperty(QObject *, const Identifier &name, const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+
+private:
+ QmlTypeNameCache::Data *lastTNData;
+ QmlPropertyCache::Data *lastData;
+ QmlPropertyCache::Data local;
+
+ PersistentIdentifier m_destroyId;
+ PersistentIdentifier m_toStringId;
+ QScriptValue m_destroy;
+ QScriptValue m_toString;
+
+ static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
+
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLOBJECTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 39fe1e2..8c46939 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -82,6 +82,8 @@ QmlParser::Object::~Object()
prop->release();
foreach(const DynamicProperty &prop, dynamicProperties)
if (prop.defaultValue) prop.defaultValue->release();
+ foreach(Object *obj, scriptBlockObjects)
+ obj->release();
}
void Object::setBindingBit(int b)
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index e0579b0..16862eb 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -151,6 +151,8 @@ namespace QmlParser
Property *defaultProperty;
QHash<QByteArray, Property *> properties;
+ QList<Object *> scriptBlockObjects;
+
// Output of the compilation phase (these properties continue to exist
// in either the defaultProperty or properties members too)
void addValueProperty(Property *);
@@ -164,6 +166,9 @@ namespace QmlParser
QList<Property *> groupedProperties;
QList<Property *> valueTypeProperties;
+ // Script blocks that were nested under this object
+ QStringList scriptBlocks;
+
// The bytes to cast instances by to get to the QmlParserStatus
// interface. -1 indicates the type doesn't support this interface.
// Set by the QmlCompiler.
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
new file mode 100644
index 0000000..63ce00c
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** 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 "qmlpropertycache_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlbinding.h>
+
+QT_BEGIN_NAMESPACE
+
+void QmlPropertyCache::Data::load(const QMetaProperty &p)
+{
+ propType = p.userType();
+ if (propType == QVariant::LastType)
+ propType = qMetaTypeId<QVariant>();
+ coreIndex = p.propertyIndex();
+ notifyIndex = p.notifySignalIndex();
+ name = QLatin1String(p.name());
+
+ if (p.isConstant())
+ flags |= Data::IsConstant;
+ if (p.isWritable())
+ flags |= Data::IsWritable;
+
+ if (propType == qMetaTypeId<QmlBinding *>()) {
+ flags |= Data::IsQmlBinding;
+ } else if (p.isEnumType()) {
+ flags |= Data::IsEnumType;
+ } else {
+ QmlMetaType::TypeCategory cat = QmlMetaType::typeCategory(propType);
+ if (cat == QmlMetaType::Object)
+ flags |= Data::IsQObjectDerived;
+ else if (cat == QmlMetaType::List)
+ flags |= Data::IsQList;
+ else if (cat == QmlMetaType::QmlList)
+ flags |= Data::IsQmlList;
+ }
+}
+
+void QmlPropertyCache::Data::load(const QMetaMethod &m)
+{
+ name = QLatin1String(m.signature());
+ int parenIdx = name.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ name = name.left(parenIdx);
+
+ coreIndex = m.methodIndex();
+ flags |= Data::IsFunction;
+}
+
+
+QmlPropertyCache::QmlPropertyCache()
+{
+}
+
+QmlPropertyCache::~QmlPropertyCache()
+{
+ for (int ii = 0; ii < indexCache.count(); ++ii)
+ indexCache.at(ii)->release();
+
+ for (StringCache::ConstIterator iter = stringCache.begin();
+ iter != stringCache.end(); ++iter)
+ (*iter)->release();
+
+ for (IdentifierCache::ConstIterator iter = identifierCache.begin();
+ iter != identifierCache.end(); ++iter)
+ (*iter)->release();
+}
+
+QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject,
+ const QString &property)
+{
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache::Data rv;
+
+ int idx = metaObject->indexOfProperty(property.toUtf8());
+ if (idx != -1) {
+ rv.load(metaObject->property(idx));
+ return rv;
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ QString methodName = QLatin1String(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (methodName == property) {
+ rv.load(m);
+ return rv;
+ }
+ }
+
+ return rv;
+}
+
+// ### Optimize - check engine for the parent meta object etc.
+QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache *cache = new QmlPropertyCache;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### The properties/methods should probably be spliced on a per-metaobject basis
+ int propCount = metaObject->propertyCount();
+
+ cache->indexCache.resize(propCount);
+ for (int ii = propCount - 1; ii >= 0; --ii) {
+ QMetaProperty p = metaObject->property(ii);
+ QString propName = QLatin1String(p.name());
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+
+ data->load(p);
+
+ cache->indexCache[ii] = data;
+
+ if (cache->stringCache.contains(propName))
+ continue;
+
+ cache->stringCache.insert(propName, data);
+ cache->identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ QString methodName = QLatin1String(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (cache->stringCache.contains(methodName))
+ continue;
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
+
+ data->load(m);
+
+ cache->stringCache.insert(methodName, data);
+ cache->identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ return cache;
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(int index) const
+{
+ if (index < 0 || index >= indexCache.count())
+ return 0;
+
+ return indexCache.at(index);
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QString &str) const
+{
+ return stringCache.value(str);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
new file mode 100644
index 0000000..f1b1219
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** 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 QMLPROPERTYCACHE_P_H
+#define QMLPROPERTYCACHE_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 <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QMetaProperty;
+class QmlPropertyCache : public QmlRefCount
+{
+public:
+ QmlPropertyCache();
+ virtual ~QmlPropertyCache();
+
+ struct Data {
+ inline Data();
+ inline bool operator==(const Data &);
+
+ enum Flag {
+ // Can apply to all properties, except IsFunction
+ IsConstant = 0x00000001,
+ IsWritable = 0x00000002,
+
+ // These are mutually exclusive
+ IsFunction = 0x00000004,
+ IsQObjectDerived = 0x00000008,
+ IsEnumType = 0x00000010,
+ IsQmlList = 0x00000020,
+ IsQList = 0x00000040,
+ IsQmlBinding = 0x00000080
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ bool isValid() const { return coreIndex != -1; }
+
+ Flags flags;
+ int propType;
+ int coreIndex;
+ int notifyIndex;
+ QString name;
+
+ void load(const QMetaProperty &);
+ void load(const QMetaMethod &);
+ };
+
+#if 0
+ struct ValueTypeData {
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+ };
+#endif
+
+ static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
+ static Data create(const QMetaObject *, const QString &);
+
+ inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
+ Data *property(const QString &) const;
+ Data *property(int) const;
+
+private:
+ struct RData : public Data, public QmlRefCount {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+
+ typedef QVector<RData *> IndexCache;
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ IndexCache indexCache;
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlPropertyCache::Data::Flags);
+
+QmlPropertyCache::Data::Data()
+: flags(0), propType(0), coreIndex(-1), notifyIndex(-1)
+{
+}
+
+bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other)
+{
+ return flags == other.flags &&
+ propType == other.propType &&
+ coreIndex == other.coreIndex &&
+ notifyIndex == other.notifyIndex &&
+ name == other.name;
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYCACHE_P_H
diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp
new file mode 100644
index 0000000..307d72f
--- /dev/null
+++ b/src/declarative/qml/qmlscript.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is just a dummy file to include the documentation
+
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element adds JavaScript snippets.
+ \ingroup group_utility
+
+ QmlScript is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component. While you can have any JavaScript code
+ within a QmlScript, it is best to limit yourself to defining functions.
+
+ \qml
+ Script {
+ function debugMyComponent() {
+ print(text.text);
+ print(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
+
+ \note QmlScript executes JavaScript as soon as it is specified.
+ When defining a component, this may be before the execution context is
+ fully specified. As a result some properties or items may not be
+ accessible. By limiting your JavaScript to defining functions that are
+ only executed later once the context is fully defined, this problem is
+ avoided.
+*/
+
+/*!
+ \qmlproperty string Script::script
+ \default
+ JavaScript code to execute.
+*/
+
+/*!
+ \qmlproperty url Script::source
+
+ Setting this property causes the Script element to read JavaScript code from
+ the file specified.
+*/
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index c126830..1c7bf83 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -289,12 +289,26 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
if (lastTypeDot >= 0)
resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
- QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ bool isScript = resolvableObjectType == QLatin1String("Script");
+
+ if (isScript) {
+ if (_stateStack.isEmpty() || _stateStack.top().property) {
+ QmlError error;
+ error.setDescription(QLatin1String("Invalid use of Script block"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ }
+ }
Object *obj = new Object;
- obj->type = typeRef->id;
- typeRef->refObjects.append(obj);
+ if (!isScript) {
+ QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ obj->type = typeRef->id;
+
+ typeRef->refObjects.append(obj);
+ }
// XXX this doesn't do anything (_scope never builds up)
_scope.append(resolvableObjectType);
@@ -303,7 +317,11 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
obj->location = location;
- if (propertyCount) {
+ if (isScript) {
+
+ _stateStack.top().object->scriptBlockObjects.append(obj);
+
+ } else if (propertyCount) {
Property *prop = currentProperty();
Value *v = new Value;
@@ -385,6 +403,26 @@ Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
_stateStack.pop(); // object
return obj;
+ } else if (objectType == QLatin1String("Script")) {
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("source")) {
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(stmt->expression);
+ if (string) {
+ // We need to add this as a resource
+ _parser->_refUrls << QUrl(string->value->asString());
+ }
+ }
+ }
+ }
+
}
return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
@@ -867,6 +905,11 @@ QList<QmlScriptParser::TypeReference*> QmlScriptParser::referencedTypes() const
return _refTypes;
}
+QList<QUrl> QmlScriptParser::referencedResources() const
+{
+ return _refUrls;
+}
+
Object *QmlScriptParser::tree() const
{
return root;
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
index d489610..b25d6bf 100644
--- a/src/declarative/qml/qmlscriptparser_p.h
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -102,6 +102,7 @@ public:
bool parse(const QByteArray &data, const QUrl &url = QUrl());
QList<TypeReference*> referencedTypes() const;
+ QList<QUrl> referencedResources() const;
QmlParser::Object *tree() const;
QList<Import> imports() const;
@@ -123,6 +124,7 @@ public:
QmlParser::Object *root;
QList<Import> _imports;
QList<TypeReference*> _refTypes;
+ QList<QUrl> _refUrls;
QString _scriptFile;
QmlScriptParserJsASTData *data;
};
diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp
new file mode 100644
index 0000000..aa1c938
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 "qmltypenamecache_p.h"
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlTypeNameCache::QmlTypeNameCache(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlTypeNameCache::~QmlTypeNameCache()
+{
+ qDeleteAll(stringCache);
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlType *type)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->type = type;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlTypeNameCache *typeNamespace)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->typeNamespace = typeNamespace;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ typeNamespace->addref();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QString &id) const
+{
+ return stringCache.value(id);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h
new file mode 100644
index 0000000..f11fe68
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 QMLTYPENAMECACHE_P_H
+#define QMLTYPENAMECACHE_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 <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlTypeNameCache : public QmlRefCount
+{
+public:
+ QmlTypeNameCache(QmlEngine *);
+ virtual ~QmlTypeNameCache();
+
+ struct Data {
+ inline Data();
+ inline ~Data();
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ };
+
+ void add(const QString &, QmlType *);
+ void add(const QString &, QmlTypeNameCache *);
+
+ Data *data(const QString &) const;
+ inline Data *data(const QScriptDeclarativeClass::Identifier &id) const;
+
+private:
+ struct RData : public Data {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+QmlTypeNameCache::Data::Data()
+: type(0), typeNamespace(0)
+{
+}
+
+QmlTypeNameCache::Data::~Data()
+{
+ if (typeNamespace) typeNamespace->release();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMECACHE_P_H
+
diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp
new file mode 100644
index 0000000..c0613d1
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** 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 "qmltypenamescriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct TypeNameData : public QScriptDeclarativeClass::Object {
+ TypeNameData(QObject *o, QmlType *t, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {}
+ TypeNameData(QObject *o, QmlTypeNameCache *n, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) {
+ if (typeNamespace) typeNamespace->addref();
+ }
+ ~TypeNameData() {
+ if (typeNamespace) typeNamespace->release();
+ }
+
+ QObject *object;
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ QmlTypeNameScriptClass::TypeNameMode mode;
+};
+
+QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+ engine(bindEngine), object(0), type(0)
+{
+}
+
+QmlTypeNameScriptClass::~QmlTypeNameScriptClass()
+{
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode));
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode));
+}
+
+QScriptClass::QueryFlags
+QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ TypeNameData *data = (TypeNameData *)obj;
+
+ object = 0;
+ type = 0;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ if (data->typeNamespace) {
+
+ QmlTypeNameCache::Data *d = data->typeNamespace->data(name);
+ if (d && d->type) {
+ type = d->type;
+ return QScriptClass::HandlesReadAccess;
+ } else {
+ return 0;
+ }
+
+ } else {
+ Q_ASSERT(data->type);
+
+ QString strName = toString(name);
+
+ if (strName.at(0).isUpper()) {
+ // Must be an enum
+ if (data->mode == IncludeEnums) {
+ // ### Optimize
+ const char *enumName = strName.toUtf8().constData();
+ 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);
+ if (value != -1) {
+ enumValue = value;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+ return 0;
+ } else if (data->object) {
+ // Must be an attached property
+ object = qmlAttachedPropertiesObjectById(data->type->index(), data->object);
+ if (!object) return 0;
+ return ep->objectClass->queryProperty(object, name, flags, 0);
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue QmlTypeNameScriptClass::property(Object *obj, const Identifier &name)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ if (type) {
+ return newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode);
+ } else if (object) {
+ return ep->objectClass->property(object, name);
+ } else {
+ return QScriptValue(enumValue);
+ }
+}
+
+void QmlTypeNameScriptClass::setProperty(Object *o, const Identifier &n, const QScriptValue &v)
+{
+ Q_ASSERT(object);
+ Q_ASSERT(!type);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h
new file mode 100644
index 0000000..d8112d2
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 QMLTYPENAMESCRIPTCLASS_P_H
+#define QMLTYPENAMESCRIPTCLASS_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 <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlType;
+class QmlTypeNameCache;
+class QmlTypeNameScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlTypeNameScriptClass(QmlEngine *);
+ ~QmlTypeNameScriptClass();
+
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ QScriptValue newObject(QObject *, QmlType *, TypeNameMode = IncludeEnums);
+ QScriptValue newObject(QObject *, QmlTypeNameCache *, TypeNameMode = IncludeEnums);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QmlEngine *engine;
+ QObject *object;
+ QmlType *type;
+ quint32 enumValue;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp
new file mode 100644
index 0000000..6fd674a
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 "qmlvaluetypescriptclass_p.h"
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QmlValueTypeReference {
+ QmlValueType *type;
+ QGuard<QObject> object;
+ int property;
+};
+Q_DECLARE_METATYPE(QmlValueTypeReference);
+
+QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine)
+: QScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
+{
+}
+
+QmlValueTypeScriptClass::~QmlValueTypeScriptClass()
+{
+}
+
+QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type)
+{
+ QmlValueTypeReference ref = { type, object, coreIndex };
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ return scriptEngine->newObject(this, scriptEngine->newVariant(qVariantFromValue(ref)));
+}
+
+QmlValueTypeScriptClass::QueryFlags
+QmlValueTypeScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return 0;
+
+ QByteArray propName = name.toString().toUtf8();
+
+ int idx = ref.type->metaObject()->indexOfProperty(propName.constData());
+ if (idx == -1)
+ return 0;
+ *id = idx;
+
+ QMetaProperty prop = ref.object->metaObject()->property(idx);
+
+ QmlValueTypeScriptClass::QueryFlags rv =
+ QmlValueTypeScriptClass::HandlesReadAccess;
+ if (prop.isWritable())
+ rv |= QmlValueTypeScriptClass::HandlesWriteAccess;
+
+ return rv;
+}
+
+QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ Q_UNUSED(name);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return QScriptValue();
+
+ ref.type->read(ref.object, ref.property);
+
+ QMetaProperty p = ref.type->metaObject()->property(id);
+ QVariant rv = p.read(ref.type);
+
+ return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv);
+}
+
+void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return;
+
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+
+ 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);
+}
+
+QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val)
+{
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(val.data().toVariant());
+
+ if (!ref.object)
+ return QVariant();
+
+ QMetaProperty p = ref.object->metaObject()->property(ref.property);
+ return p.read(ref.object);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h
new file mode 100644
index 0000000..d656a22
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 QMLVALUETYPESCRIPTCLASS_P_H
+#define QMLVALUETYPESCRIPTCLASS_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 <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlValueType;
+class QmlValueTypeScriptClass : public QScriptClass
+{
+public:
+ QmlValueTypeScriptClass(QmlEngine *);
+ ~QmlValueTypeScriptClass();
+
+ QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *);
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+
+ QVariant toVariant(const QScriptValue &);
+private:
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVALUETYPESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 44b17e6..e4eef64 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -143,6 +143,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
const QList<int> &intData = comp->intData;
const QList<float> &floatData = comp->floatData;
+ const QList<QmlPropertyCache *> &propertyCaches = comp->propertyCaches;
QmlEnginePrivate::SimpleList<QmlAbstractBinding> bindValues;
@@ -165,8 +166,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (instr.init.parserStatusSize)
parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
- if (instr.init.idSize)
- cp->setIdPropertyCount(instr.init.idSize);
+ if (instr.init.contextCache != -1)
+ cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
}
break;
@@ -259,9 +260,15 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
const QByteArray &metadata = datas.at(instr.storeMeta.data);
QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
- const QmlVMEMetaData *data = (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
+ const QmlVMEMetaData *data =
+ (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
(void)new QmlVMEMetaObject(target, &mo, data, comp);
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(target, true);
+ if (ddata->propertyCache) ddata->propertyCache->release();
+ ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
+ ddata->propertyCache->addref();
}
break;
@@ -557,6 +564,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
}
break;
+ case QmlInstruction::StoreScript:
+ {
+ QObject *target = stack.top();
+ cp->addScript(primitives.at(instr.storeScript.value), target);
+ }
+ break;
+
case QmlInstruction::BeginObject:
{
QObject *target = stack.top();
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
index 912bb6b..7df8453 100644
--- a/src/declarative/util/qmlpackage.cpp
+++ b/src/declarative/util/qmlpackage.cpp
@@ -55,11 +55,11 @@ public:
class QmlPackageAttached : public QObject
{
Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
public:
QmlPackageAttached(QObject *parent);
virtual ~QmlPackageAttached();
- Q_PROPERTY(QString name READ name WRITE setName)
QString name() const;
void setName(const QString &n);
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
deleted file mode 100644
index de2128d..0000000
--- a/src/declarative/util/qmlscript.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtDeclarative/qmlengine.h>
-#include <QtDeclarative/qmlcontext.h>
-#include <private/qobject_p.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qdebug.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
-#include <private/qmlnullablevalue_p.h>
-#include <private/qmlengine_p.h>
-#include <private/qmlcontext_p.h>
-#include "qmlscript.h"
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QtDeclarative/qmlinfo.h>
-#include <private/qfxperf_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QmlScriptPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QmlScript);
-
-public:
- QmlScriptPrivate() : reply(0) {}
-
- void addScriptToEngine(const QString &, const QString &source=QString());
-
- QString script;
- QNetworkReply *reply;
- QUrl url;
-};
-
-/*!
- \qmlclass Script QmlScript
- \brief The Script element adds JavaScript snippets.
- \ingroup group_utility
-
- QmlScript is used to add convenient JavaScript "glue" methods to
- your Qt Declarative application or component. While you can have any JavaScript code
- within a QmlScript, it is best to limit yourself to defining functions.
-
- \qml
- Script {
- function debugMyComponent() {
- print(text.text);
- print(otherinterestingitem.property);
- }
- }
- MouseRegion { onClicked: debugMyComponent() }
- \endqml
-
- \note QmlScript executes JavaScript as soon as it is specified.
- When defining a component, this may be before the execution context is
- fully specified. As a result some properties or items may not be
- accessible. By limiting your JavaScript to defining functions that are
- only executed later once the context is fully defined, this problem is
- avoided.
-*/
-
-QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Script,QmlScript)
-QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent)
-{
-}
-
-/*!
- \qmlproperty string Script::script
- \default
- JavaScript code to execute.
-*/
-QString QmlScript::script() const
-{
- Q_D(const QmlScript);
- return d->script;
-}
-
-void QmlScript::setScript(const QString &script)
-{
- Q_D(QmlScript);
- d->script = script;
- d->addScriptToEngine(d->script);
-}
-
-/*!
- \qmlproperty url Script::source
-
- Setting this property causes the Script element to read JavaScript code from
- the file specified.
-*/
-QUrl QmlScript::source() const
-{
- Q_D(const QmlScript);
- return d->url;
-}
-
-void QmlScript::setSource(const QUrl &source)
-{
- Q_D(QmlScript);
- if (d->url == source)
- return;
- d->url = qmlContext(this)->resolvedUrl(source);
-
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- if (d->url.scheme() == QLatin1String("file")) {
- QFile file(d->url.toLocalFile());
- file.open(QIODevice::ReadOnly);
- QByteArray ba = file.readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), file.fileName());
- } else
-#endif
- {
- QNetworkRequest req(d->url);
- d->reply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->reply, SIGNAL(finished()),
- this, SLOT(replyFinished()));
- }
-}
-
-void QmlScript::replyFinished()
-{
- Q_D(QmlScript);
- if (!d->reply->error()) {
- QByteArray ba = d->reply->readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), d->url.toString());
- }
- d->reply->deleteLater();
- d->reply = 0;
-}
-
-void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &source)
-{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QFxPerfTimer<QFxPerf::AddScript> pt;
-#endif
- Q_Q(QmlScript);
- QmlEngine *engine = qmlEngine(q);
- QmlContext *context = qmlContext(q);
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
-
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) {
- scriptContext->pushScope(context->d_func()->scopeChain.at(i));
- }
- scriptContext->setActivationObject(context->d_func()->scopeChain.at(0));
-
- QScriptValue val = scriptEngine->evaluate(script, source);
- 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(q) << exception.toString();
- }
- }
- }
-
- scriptEngine->popContext();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index 41c9019..ec9967c 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -4,7 +4,6 @@ SOURCES += \
util/qperformancelog.cpp \
util/qmlconnection.cpp \
util/qmlpackage.cpp \
- util/qmlscript.cpp \
util/qmlanimation.cpp \
util/qmlsystempalette.cpp \
util/qmlspringfollow.cpp \
@@ -29,7 +28,6 @@ HEADERS += \
util/qperformancelog_p.h \
util/qmlconnection.h \
util/qmlpackage.h \
- util/qmlscript.h \
util/qmlanimation.h \
util/qmlanimation_p.h \
util/qmlsystempalette.h \