summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/qml
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qml.h98
-rw-r--r--src/declarative/qml/qml.pri63
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp210
-rw-r--r--src/declarative/qml/qmlbindablevalue.h94
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp158
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h104
-rw-r--r--src/declarative/qml/qmlclassfactory.cpp47
-rw-r--r--src/declarative/qml/qmlclassfactory_p.h63
-rw-r--r--src/declarative/qml/qmlcompiledcomponent.cpp170
-rw-r--r--src/declarative/qml/qmlcompiledcomponent_p.h80
-rw-r--r--src/declarative/qml/qmlcompiler.cpp1662
-rw-r--r--src/declarative/qml/qmlcompiler_p.h183
-rw-r--r--src/declarative/qml/qmlcomponent.cpp405
-rw-r--r--src/declarative/qml/qmlcomponent.h102
-rw-r--r--src/declarative/qml/qmlcomponent_p.h85
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp359
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h144
-rw-r--r--src/declarative/qml/qmlcontext.cpp405
-rw-r--r--src/declarative/qml/qmlcontext.h104
-rw-r--r--src/declarative/qml/qmlcontext_p.h87
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp96
-rw-r--r--src/declarative/qml/qmlcustomparser.h82
-rw-r--r--src/declarative/qml/qmldom.cpp1372
-rw-r--r--src/declarative/qml/qmldom.h263
-rw-r--r--src/declarative/qml/qmldom_p.h116
-rw-r--r--src/declarative/qml/qmlengine.cpp1295
-rw-r--r--src/declarative/qml/qmlengine.h107
-rw-r--r--src/declarative/qml/qmlengine_p.h215
-rw-r--r--src/declarative/qml/qmlexpression.h115
-rw-r--r--src/declarative/qml/qmlinfo.cpp97
-rw-r--r--src/declarative/qml/qmlinfo.h69
-rw-r--r--src/declarative/qml/qmlinstruction.cpp214
-rw-r--r--src/declarative/qml/qmlinstruction_p.h299
-rw-r--r--src/declarative/qml/qmllist.h125
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp847
-rw-r--r--src/declarative/qml/qmlmetaproperty.h137
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h75
-rw-r--r--src/declarative/qml/qmlmetatype.cpp1164
-rw-r--r--src/declarative/qml/qmlmetatype.h258
-rw-r--r--src/declarative/qml/qmlparser.cpp167
-rw-r--r--src/declarative/qml/qmlparser_p.h209
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp75
-rw-r--r--src/declarative/qml/qmlparserstatus.h69
-rw-r--r--src/declarative/qml/qmlprivate.cpp48
-rw-r--r--src/declarative/qml/qmlprivate.h365
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.cpp75
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.h79
-rw-r--r--src/declarative/qml/qmlproxymetaobject.cpp113
-rw-r--r--src/declarative/qml/qmlproxymetaobject_p.h85
-rw-r--r--src/declarative/qml/qmlrefcount.cpp66
-rw-r--r--src/declarative/qml/qmlrefcount_p.h69
-rw-r--r--src/declarative/qml/qmlstringconverters.cpp212
-rw-r--r--src/declarative/qml/qmlstringconverters_p.h68
-rw-r--r--src/declarative/qml/qmlvme.cpp1345
-rw-r--r--src/declarative/qml/qmlvme_p.h75
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp140
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h71
-rw-r--r--src/declarative/qml/qmlxmlparser.cpp384
-rw-r--r--src/declarative/qml/qmlxmlparser_p.h88
-rw-r--r--src/declarative/qml/script/generator/generator.pro11
-rw-r--r--src/declarative/qml/script/generator/main.cpp135
-rw-r--r--src/declarative/qml/script/instructions.h32
-rw-r--r--src/declarative/qml/script/keywords.cpp89
-rw-r--r--src/declarative/qml/script/lexer.cpp139
-rw-r--r--src/declarative/qml/script/lexer.h54
-rw-r--r--src/declarative/qml/script/qmlbasicscript.cpp923
-rw-r--r--src/declarative/qml/script/qmlbasicscript.h76
-rw-r--r--src/declarative/qml/script/qmlbasicscript_p.h52
-rw-r--r--src/declarative/qml/script/script.pri11
-rw-r--r--src/declarative/qml/script/tokens.cpp44
-rw-r--r--src/declarative/qml/script/tokens.h36
71 files changed, 16974 insertions, 0 deletions
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h
new file mode 100644
index 0000000..bf7b6bc
--- /dev/null
+++ b/src/declarative/qml/qml.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 QML_H
+#define QML_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmllist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#define QML_DECLARE_TYPE(TYPE) \
+ Q_DECLARE_METATYPE(TYPE *); \
+ Q_DECLARE_METATYPE(QList<TYPE *> *); \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *);
+
+#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *); \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *);
+
+#define QML_DECLARE_INTERFACE(INTERFACE) \
+ QML_DECLARE_TYPE(INTERFACE)
+
+#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
+ QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<INTERFACE *>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE));
+
+#define QML_DEFINE_EXTENDED_TYPE(TYPE, NAME, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#NAME, #TYPE));
+
+#define QML_DEFINE_TYPE(TYPE, NAME) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#NAME, #TYPE));
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE));
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *>::instance(qmlRegisterType<TYPE>(#TYPE));
+
+QML_DECLARE_TYPE(QObject);
+Q_DECLARE_METATYPE(QVariant);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QML_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
new file mode 100644
index 0000000..65e6763
--- /dev/null
+++ b/src/declarative/qml/qml.pri
@@ -0,0 +1,63 @@
+SOURCES += qml/qmlparser.cpp \
+ qml/qmlinstruction.cpp \
+ qml/qmlvmemetaobject.cpp \
+ qml/qmlengine.cpp \
+ qml/qmlbindablevalue.cpp \
+ qml/qmlmetaproperty.cpp \
+ qml/qmlcomponent.cpp \
+ qml/qmlcontext.cpp \
+ qml/qmlcustomparser.cpp \
+ qml/qmlpropertyvaluesource.cpp \
+ qml/qmlxmlparser.cpp \
+ qml/qmlproxymetaobject.cpp \
+ qml/qmlvme.cpp \
+ qml/qmlcompiler.cpp \
+ qml/qmlcompiledcomponent.cpp \
+ qml/qmlboundsignal.cpp \
+ qml/qmldom.cpp \
+ qml/qmlrefcount.cpp \
+ qml/qmlprivate.cpp \
+ qml/qmlmetatype.cpp \
+ qml/qmlstringconverters.cpp \
+ qml/qmlclassfactory.cpp \
+ qml/qmlparserstatus.cpp \
+ qml/qmlcompositetypemanager.cpp \
+ qml/qmlinfo.cpp
+
+HEADERS += qml/qmlparser_p.h \
+ qml/qmlinstruction_p.h \
+ qml/qmlvmemetaobject_p.h \
+ qml/qml.h \
+ qml/qmlbindablevalue.h \
+ qml/qmlmetaproperty.h \
+ qml/qmlcomponent.h \
+ qml/qmlcomponent_p.h \
+ qml/qmlcustomparser.h \
+ qml/qmlpropertyvaluesource.h \
+ qml/qmlboundsignal_p.h \
+ qml/qmlxmlparser_p.h \
+ qml/qmlparserstatus.h \
+ qml/qmlproxymetaobject_p.h \
+ qml/qmlcompiledcomponent_p.h \
+ qml/qmlvme_p.h \
+ qml/qmlcompiler_p.h \
+ qml/qmlengine_p.h \
+ qml/qmlprivate.h \
+ qml/qmldom.h \
+ qml/qmldom_p.h \
+ qml/qmlrefcount_p.h \
+ qml/qmlmetatype.h \
+ qml/qmlengine.h \
+ qml/qmlcontext.h \
+ qml/qmlexpression.h \
+ qml/qmlstringconverters_p.h \
+ qml/qmlclassfactory_p.h \
+ qml/qmlinfo.h \
+ qml/qmlmetaproperty_p.h \
+ qml/qmlcontext_p.h \
+ qml/qmlcompositetypemanager_p.h \
+ qml/qmllist.h
+
+# for qtscript debugger
+QT += scripttools
+include(script/script.pri)
diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp
new file mode 100644
index 0000000..423fda8
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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 <qml.h>
+#include "qmlbindablevalue.h"
+#include <gfxeasing.h>
+#include <qmlcontext.h>
+#include <gfxtimeline.h>
+#include <QVariant>
+#include <qfxperf.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+QML_DEFINE_NOCREATE_TYPE(QmlBindableValue);
+QmlBindableValue::QmlBindableValue(QObject *parent)
+: QmlPropertyValueSource(parent), _inited(false)
+{
+ qFatal("QmlBindableValue: Default constructor not supported");
+}
+
+QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QObject *parent)
+: QmlPropertyValueSource(parent), QmlExpression(QmlContext::activeContext(), data, rc, obj), _inited(false)
+{
+}
+
+QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, bool sse, QObject *parent)
+: QmlPropertyValueSource(parent), QmlExpression(QmlContext::activeContext(), str, obj, sse), _inited(false)
+{
+}
+
+QmlBindableValue::~QmlBindableValue()
+{
+}
+
+void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
+{
+ _property = prop;
+
+ update();
+}
+
+void QmlBindableValue::init()
+{
+ if(_inited)
+ return;
+ _inited = true;
+ update();
+}
+
+void QmlBindableValue::setExpression(const QString &expr)
+{
+ QmlExpression::setExpression(expr);
+ update();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void QmlBindableValue::update()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
+#endif
+ if(!_inited)
+ return;
+
+ if(_property.propertyCategory() == QmlMetaProperty::List) {
+ QVariant value = this->value();
+ int listType = QmlMetaType::listType(_property.propertyType());
+
+ if(value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = _property.read();
+ QmlMetaType::clear(listVar);
+ for(int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if(value.type() == uint(listType) ||
+ value.userType() == listType) {
+ QVariant listVar = _property.read();
+ QmlMetaType::clear(listVar);
+ QmlMetaType::append(listVar, value);
+ }
+ } else if(_property.propertyCategory() == QmlMetaProperty::QmlList) {
+ // XXX - optimize!
+ QVariant value = this->value();
+ QVariant list = _property.read();
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if(objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if(!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if(_property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Bindable
+ int idx = _property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ QmlBindableValue *t = this;
+ a[0] = (void *)&t;
+ _property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if(_property.propertyCategory() == QmlMetaProperty::Object) {
+
+ QVariant value = this->value();
+ if((int)value.type() != qMetaTypeId<QObject *>()) {
+ if(scriptWarnings()) {
+ if(!value.isValid()) {
+ qWarning() << "QmlBindableValue: Unable to assign invalid value to object property";
+ } else {
+ qWarning() << "QmlBindableValue: Unable to assign non-object to object property";
+ }
+ }
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *obj = *(QObject **)value.data();
+
+ // NOTE: We assume that only core properties can have
+ // propertyType == Object
+ int idx = _property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+ void *a[1];
+ a[0] = (void *)&obj;
+ _property.object()->qt_metacall(QMetaObject::WriteProperty,
+ idx, a);
+
+ } else if(_property.propertyCategory() == QmlMetaProperty::Normal) {
+ QVariant value = this->value();
+ _property.write(value);
+ }
+}
+
+void QmlBindableValue::valueChanged()
+{
+ update();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindablevalue.h b/src/declarative/qml/qmlbindablevalue.h
new file mode 100644
index 0000000..578fc12
--- /dev/null
+++ b/src/declarative/qml/qmlbindablevalue.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QMLBINDABLEVALUE_H
+#define QMLBINDABLEVALUE_H
+
+#include <QObject>
+#include <qfxglobal.h>
+#include <qml.h>
+#include <qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlexpression.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlExpression;
+class QmlContext;
+class Q_DECLARATIVE_EXPORT QmlBindableValue : public QmlPropertyValueSource,
+ public QmlExpression
+{
+Q_OBJECT
+public:
+ QmlBindableValue(QObject *parent);
+ QmlBindableValue(const QString &, QObject *, bool = true, QObject *parent=0);
+ QmlBindableValue(void *, QmlRefCount *, QObject *, QObject *parent);
+ ~QmlBindableValue();
+
+ virtual void setTarget(const QmlMetaProperty &);
+ QmlMetaProperty property() const { return _property; }
+
+ Q_CLASSINFO("DefaultProperty", "expression");
+ Q_PROPERTY(QString expression READ expression WRITE setExpression);
+ virtual void setExpression(const QString &);
+
+ void init();
+
+private Q_SLOTS:
+ void update();
+
+protected:
+ virtual void valueChanged();
+
+private:
+ bool _inited;
+ QmlMetaProperty _property;
+};
+QML_DECLARE_TYPE(QmlBindableValue);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QMLBINDABLEVALUE_H
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
new file mode 100644
index 0000000..5359753
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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 "qmlboundsignal_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "private/qmlengine_p.h"
+#include "private/qmlcontext_p.h"
+#include <qfxglobal.h>
+#include <qmlmetatype.h>
+#include <qml.h>
+#include <qmlcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+int QmlBoundSignal::evaluateIdx = -1;
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlExpressionObject(ctxt, val, me, false), _idx(idx)
+{
+ // A cached evaluation of the QmlExpressionObject::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if(evaluateIdx == -1) evaluateIdx = QmlExpressionObject::staticMetaObject.indexOfMethod("value()");
+
+ setTrackChange(false);
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(me, _idx, this, evaluateIdx);
+}
+
+QmlBoundSignalProxy::QmlBoundSignalProxy(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
+: QmlBoundSignal(ctxt, val, me, idx, parent)
+{
+ QMetaMethod signal = me->metaObject()->method(idx);
+
+ params = new QmlBoundSignalParameters(signal, this);
+
+ ctxt->d_func()->addDefaultObject(params, QmlContextPrivate::HighPriority);
+}
+
+int QmlBoundSignalProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ if(c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
+ params->setValues(a);
+ value();
+ params->clearValues();
+ return -1;
+ } else {
+ return QmlBoundSignal::qt_metacall(c, id, a);
+ }
+}
+
+#include <QDebug>
+QmlBoundSignalParameters::QmlBoundSignalParameters(const QMetaMethod &method,
+ QObject *parent)
+: QObject(parent), types(0), values(0)
+{
+ MetaObject *mo = new MetaObject(this);
+
+ // ### Optimize!
+ // ### Ensure only supported types are allowed, otherwise it might crash
+ QMetaObjectBuilder mob;
+ mob.setSuperClass(&QmlBoundSignalParameters::staticMetaObject);
+
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<QByteArray> paramNames = method.parameterNames();
+ types = new int[paramTypes.count()];
+ for(int ii = 0; ii < paramTypes.count(); ++ii) {
+ const QByteArray &type = paramTypes.at(ii);
+ const QByteArray &name = paramNames.at(ii);
+
+ if(name.isEmpty() || type.isEmpty()) {
+ types[ii] = 0;
+ continue;
+ }
+
+ QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ if(QmlMetaType::isObject(t)) {
+ types[ii] = QMetaType::QObjectStar;
+ QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
+ prop.setWritable(false);
+ } else {
+ types[ii] = t;
+ QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ prop.setWritable(false);
+ }
+ }
+ myMetaObject = mob.toMetaObject();
+ *static_cast<QMetaObject *>(mo) = *myMetaObject;
+
+ d_ptr->metaObject = mo;
+}
+
+QmlBoundSignalParameters::~QmlBoundSignalParameters()
+{
+ delete [] types;
+ qFree(myMetaObject);
+}
+
+void QmlBoundSignalParameters::setValues(void **v)
+{
+ values = v;
+}
+
+void QmlBoundSignalParameters::clearValues()
+{
+ values = 0;
+}
+
+int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if(c == QMetaObject::ReadProperty && id >= 1) {
+ QmlMetaType::copy(types[id - 1], a[0], values[id]);
+ return -1;
+ } else {
+ return qt_metacall(c, id, a);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
new file mode 100644
index 0000000..e84f0c1
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 QMLBOUNDSIGNAL_P_H
+#define QMLBOUNDSIGNAL_P_H
+
+#include <qmlexpression.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlBoundSignal : public QmlExpressionObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignal(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+ int index() const { return _idx; }
+protected:
+ static int evaluateIdx;
+private:
+ int _idx;
+};
+
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+class QmlBoundSignalProxy : public QmlBoundSignal
+{
+public:
+ QmlBoundSignalProxy(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+
+protected:
+ virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+private:
+ QmlBoundSignalParameters *params;
+};
+
+
+#endif // QMLBOUNDSIGNAL_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlclassfactory.cpp b/src/declarative/qml/qmlclassfactory.cpp
new file mode 100644
index 0000000..7e5b929
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 "qmlclassfactory_p.h"
+
+QmlClassFactory::~QmlClassFactory()
+{
+}
+
diff --git a/src/declarative/qml/qmlclassfactory_p.h b/src/declarative/qml/qmlclassfactory_p.h
new file mode 100644
index 0000000..e3e71c9
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 QMLCLASSFACTORY_P_H
+#define QMLCLASSFACTORY_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QByteArray;
+class QUrl;
+class QmlComponent;
+
+class QmlClassFactory
+{
+public:
+ virtual ~QmlClassFactory();
+ virtual QmlComponent *create(const QByteArray &, const QUrl& baseUrl, QmlEngine*) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLASSFACTORY_P_H
diff --git a/src/declarative/qml/qmlcompiledcomponent.cpp b/src/declarative/qml/qmlcompiledcomponent.cpp
new file mode 100644
index 0000000..a8b2be0
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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 "qmlcompiledcomponent_p.h"
+#include "qmlparser_p.h"
+#include <QtCore/qdebug.h>
+#include <QmlComponent>
+using namespace QmlParser;
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
+
+QmlCompiledComponent::QmlCompiledComponent()
+: dumpStatus(NoDump)
+{
+}
+
+QmlCompiledComponent::~QmlCompiledComponent()
+{
+ for(int ii = 0; ii < mos.count(); ++ii)
+ qFree(mos.at(ii));
+}
+
+
+void QmlCompiledComponent::dumpInstructions()
+{
+ if(!compilerDump())
+ return;
+
+ if(!name.isEmpty())
+ qWarning() << name;
+ qWarning() << "Index\tLine\tOperation\t\tData1\tData2\t\tComments";
+ qWarning() << "-------------------------------------------------------------------------------";
+ for(int ii = 0; ii < bytecode.count(); ++ii) {
+ dump(&bytecode[ii], ii);
+ }
+ qWarning() << "-------------------------------------------------------------------------------";
+}
+
+void QmlCompiledComponent::dump(int indent, Property *p)
+{
+ QByteArray ba(indent * 4, ' ');
+ for(int ii = 0; ii < p->values.count(); ++ii)
+ dump(indent, p->values.at(ii));
+ if(p->value)
+ dump(indent, p->value);
+}
+
+void QmlCompiledComponent::dump(int indent, Object *o)
+{
+ QByteArray ba(indent * 4, ' ');
+ if(o->type != -1) {
+ qWarning() << ba.constData() << "Object:" << types.at(o->type).className;
+ } else {
+ qWarning() << ba.constData() << "Object: fetched";
+ }
+
+ for(QHash<QByteArray, Property *>::ConstIterator iter = o->properties.begin();
+ iter != o->properties.end();
+ ++iter) {
+ qWarning() << ba.constData() << " Property" << iter.key();
+ dump(indent + 1, *iter);
+ }
+
+ if(o->defaultProperty) {
+ qWarning() << ba.constData() << " Default property";
+ dump(indent + 1, o->defaultProperty);
+ }
+}
+
+void QmlCompiledComponent::dump(int indent, Value *v)
+{
+ QByteArray type;
+ switch(v->type) {
+ default:
+ case Value::Unknown:
+ type = "Unknown";
+ break;
+ case Value::Literal:
+ type = "Literal";
+ break;
+ case Value::PropertyBinding:
+ type = "PropertyBinding";
+ break;
+ case Value::ValueSource:
+ type = "ValueSource";
+ break;
+ case Value::CreatedObject:
+ type = "CreatedObject";
+ break;
+ case Value::SignalObject:
+ type = "SignalObject";
+ break;
+ case Value::SignalExpression:
+ type = "SignalExpression";
+ break;
+ case Value::Component:
+ type = "Component";
+ break;
+ case Value::Id:
+ type = "Id";
+ break;
+ };
+
+ QByteArray ba(indent * 4, ' ');
+ if(v->object) {
+ qWarning() << ba.constData() << "Value (" << type << "):";
+ dump(indent + 1, v->object);
+ } else {
+ qWarning() << ba.constData() << "Value (" << type << "):" << v->primitive;
+ }
+}
+
+void QmlCompiledComponent::dumpPre()
+{
+ if(!(dumpStatus & DumpPre)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPre);
+ }
+}
+
+void QmlCompiledComponent::dumpPost()
+{
+ if(!(dumpStatus & DumpPost)) {
+ dumpInstructions();
+ dumpStatus = (DumpStatus)(dumpStatus | DumpPost);
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiledcomponent_p.h b/src/declarative/qml/qmlcompiledcomponent_p.h
new file mode 100644
index 0000000..fa68eab
--- /dev/null
+++ b/src/declarative/qml/qmlcompiledcomponent_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QMLCOMPILEDCOMPONENT_P_H
+#define QMLCOMPILEDCOMPONENT_P_H
+
+#include <qml.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompiler_p.h>
+#include <private/qmlrefcount_p.h>
+class QmlXmlParser;
+
+QT_BEGIN_NAMESPACE
+namespace QmlParser {
+ class Property;
+ class Object;
+ class Value;
+};
+
+class QmlCompiledComponent : public QmlRefCount, public QmlCompiledData
+{
+public:
+ QmlCompiledComponent();
+ ~QmlCompiledComponent();
+
+ void dumpPre();
+ void dumpPost();
+
+private:
+ enum DumpStatus { NoDump = 0x00, DumpPre = 0x01, DumpPost = 0x02 } dumpStatus;
+ void dumpInstructions();
+ void dump(int indent, QmlParser::Property *p);
+ void dump(int indent, QmlParser::Object *o);
+ void dump(int indent, QmlParser::Value *v);
+ void dump(QmlInstruction *, int idx = -1);
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+};
+
+
+QT_END_NAMESPACE
+#endif // QMLCOMPILEDCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
new file mode 100644
index 0000000..9af0a06
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -0,0 +1,1662 @@
+/****************************************************************************
+**
+** 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 "private/qmlcompiler_p.h"
+#include <qfxperf.h>
+#include "qmlparser_p.h"
+#include "private/qmlxmlparser_p.h"
+#include <qmlpropertyvaluesource.h>
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <qmlbasicscript.h>
+#include <QColor>
+#include <QDebug>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlcompiledcomponent_p.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+/*
+ New properties and signals can be added to any QObject type from QML.
+ <QObject>
+ <properties><Property name="myProperty" /></properties>
+ <signals><Signal name="mySignal" /></signals>
+ </QObject
+ The special names used as magical properties (in the above case "properties"
+ and "signals") are defined here.
+*/
+#define PROPERTIES_NAME "properties"
+#define SIGNALS_NAME "signals"
+
+using namespace QmlParser;
+
+int QmlCompiledData::indexForString(const QString &data)
+{
+ int idx = primitives.indexOf(data);
+ if(idx == -1) {
+ idx = primitives.count();
+ primitives << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForByteArray(const QByteArray &data)
+{
+ int idx = datas.indexOf(data);
+ if(idx == -1) {
+ idx = datas.count();
+ datas << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForFloat(float *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for(int ii = 0; ii < floatData.count() - count; ++ii) {
+ bool found = true;
+ for(int jj = 0; jj < count; ++jj) {
+ if(floatData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if(found)
+ return ii;
+ }
+
+ int idx = floatData.count();
+ for(int ii = 0; ii < count; ++ii)
+ floatData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForInt(int *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for(int ii = 0; ii < floatData.count() - count; ++ii) {
+ bool found = true;
+ for(int jj = 0; jj < count; ++jj) {
+ if(intData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if(found)
+ return ii;
+ }
+
+ int idx = intData.count();
+ for(int ii = 0; ii < count; ++ii)
+ intData << data[ii];
+
+ return idx;
+}
+
+QmlCompiler::QmlCompiler()
+: exceptionLine(-1), output(0)
+{
+}
+
+bool QmlCompiler::isError() const
+{
+ return exceptionLine != -1;
+}
+
+qint64 QmlCompiler::errorLine() const
+{
+ return exceptionLine;
+}
+
+QString QmlCompiler::errorDescription() const
+{
+ return exceptionDescription;
+}
+
+bool QmlCompiler::isValidId(const QString &val)
+{
+ if(val.isEmpty())
+ return false;
+
+ QChar u(QLatin1Char('_'));
+ for(int ii = 0; ii < val.count(); ++ii)
+ if(val.at(ii) != u &&
+ ((ii == 0 && !val.at(ii).isLetter()) ||
+ (ii != 0 && !val.at(ii).isLetterOrNumber())) )
+ return false;
+
+ return true;
+}
+
+/*!
+ Returns true if \a str is a valid binding string, false otherwise.
+
+ Valid binding strings are those enclosed in braces ({}).
+*/
+bool QmlCompiler::isBinding(const QString &str)
+{
+ return str.startsWith(QLatin1Char('{')) && str.endsWith(QLatin1Char('}'));
+}
+
+/*!
+ Returns true if property name \a name refers to an attached property, false
+ otherwise.
+
+ Attached property names are those that start with a capital letter.
+*/
+bool QmlCompiler::isAttachedProperty(const QByteArray &name)
+{
+ return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+}
+
+QmlCompiler::StoreInstructionResult
+QmlCompiler::generateStoreInstruction(QmlCompiledData &cdata,
+ QmlInstruction &instr,
+ const QMetaProperty &prop,
+ int coreIdx, int primitive,
+ const QString *string)
+{
+ if(!prop.isWritable())
+ return ReadOnly;
+ if(prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string->toLatin1().constData());
+ } else
+ value = prop.enumerator().keyToValue(string->toLatin1().constData());
+ if(value == -1)
+ return InvalidData;
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ instr.storeInteger.value = value;
+ return Ok;
+ }
+ int type = prop.type();
+ switch(type) {
+ case -1:
+ instr.type = QmlInstruction::StoreVariant;
+ instr.storeString.propertyIndex = coreIdx;
+ if(primitive == -1)
+ primitive = cdata.indexForString(*string);
+ instr.storeString.value = primitive;
+ break;
+ break;
+ case QVariant::String:
+ {
+ instr.type = QmlInstruction::StoreString;
+ instr.storeString.propertyIndex = coreIdx;
+ if(string->startsWith(QLatin1Char('\'')) && string->endsWith(QLatin1Char('\''))) {
+ QString unquotedString = string->mid(1, string->length() - 2);
+ primitive = cdata.indexForString(unquotedString);
+ } else {
+ if(primitive == -1)
+ primitive = cdata.indexForString(*string);
+ }
+ instr.storeString.value = primitive;
+ }
+ break;
+ case QVariant::UInt:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ bool ok;
+ int value = string->toUInt(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeInteger.value = value;
+ }
+ break;
+ case QVariant::Int:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = coreIdx;
+ bool ok;
+ int value = string->toInt(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeInteger.value = value;
+ }
+ break;
+ case 135:
+ case QVariant::Double:
+ {
+ instr.type = QmlInstruction::StoreReal;
+ instr.storeReal.propertyIndex = coreIdx;
+ bool ok;
+ float value = string->toFloat(&ok);
+ if (!ok)
+ return InvalidData;
+ instr.storeReal.value = value;
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(*string);
+ if (!c.isValid())
+ return InvalidData;
+ instr.type = QmlInstruction::StoreColor;
+ instr.storeColor.propertyIndex = coreIdx;
+ instr.storeColor.value = c.rgba();
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(*string, Qt::ISODate);
+ if (!d.isValid())
+ return InvalidData;
+ instr.type = QmlInstruction::StoreDate;
+ instr.storeDate.propertyIndex = coreIdx;
+ instr.storeDate.value = d.toJulianDay();
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(*string, Qt::ISODate);
+ if (!time.isValid())
+ return InvalidData;
+ int data[] = { time.hour(), time.minute(), time.second(), time.msec() };
+ int index = cdata.indexForInt(data, 4);
+ instr.type = QmlInstruction::StoreTime;
+ instr.storeTime.propertyIndex = coreIdx;
+ instr.storeTime.valueIndex = index;
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(*string, Qt::ISODate);
+ if (!dateTime.isValid())
+ return InvalidData;
+ int data[] = { dateTime.date().toJulianDay(),
+ dateTime.time().hour(),
+ dateTime.time().minute(),
+ dateTime.time().second(),
+ dateTime.time().msec() };
+ int index = cdata.indexForInt(data, 5);
+ instr.type = QmlInstruction::StoreDateTime;
+ instr.storeDateTime.propertyIndex = coreIdx;
+ instr.storeDateTime.valueIndex = index;
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { point.x(), point.y() };
+ int index = cdata.indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = coreIdx;
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { size.width(), size.height() };
+ int index = cdata.indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = coreIdx;
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = cdata.indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = coreIdx;
+ instr.storeRect.valueIndex = index;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool ok;
+ bool b = QmlStringConverters::boolFromString(*string, &ok);
+ if (!ok)
+ return InvalidData;
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = coreIdx;
+ instr.storeBool.value = b;
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if(t == QVariant::UserType)
+ t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (converter) {
+ int index = cdata.customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = coreIdx;
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ if(primitive == -1)
+ primitive = cdata.indexForString(*string);
+ data.index = primitive;
+ data.type = t;
+ cdata.customTypeData << data;
+ break;
+ }
+ }
+ return UnknownType;
+ break;
+ }
+ return Ok;
+}
+
+void QmlCompiler::reset(QmlCompiledComponent *cc, bool deleteMemory)
+{
+ cc->types.clear();
+ cc->primitives.clear();
+ cc->floatData.clear();
+ cc->intData.clear();
+ cc->customTypeData.clear();
+ cc->datas.clear();
+ if(deleteMemory) {
+ for(int ii = 0; ii < cc->mos.count(); ++ii)
+ qFree(cc->mos.at(ii));
+ }
+ cc->mos.clear();
+ cc->bytecode.clear();
+}
+
+#define COMPILE_EXCEPTION(desc) \
+ { \
+ exceptionLine = obj->line; \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ return false; \
+ }
+
+#define COMPILE_CHECK(a) \
+ { \
+ if (!a) return false; \
+ }
+
+bool QmlCompiler::compile(QmlEngine *engine,
+ QmlCompositeTypeManager::TypeData *unit,
+ QmlCompiledComponent *out)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::Compile> pc;
+#endif
+ exceptionLine = -1;
+
+ Q_ASSERT(out);
+ reset(out, true);
+
+ output = out;
+
+ // Compile types
+ for(int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeManager::TypeData::TypeReference &tref = unit->types[ii];
+ QmlCompiledComponent::TypeReference ref;
+ if(tref.type)
+ ref.type = tref.type;
+ else if(tref.unit) {
+ ref.component = tref.unit->toComponent(engine);
+ ref.ref = tref.unit;
+ ref.ref->addref();
+ } else if(tref.parser)
+ ref.parser = tref.parser;
+ ref.className = unit->data.types().at(ii).toLatin1();
+ out->types << ref;
+ }
+
+ Object *root = unit->data.tree();
+ if(!root) {
+ exceptionDescription = QLatin1String("Can't compile because of earlier errors");
+ output = 0;
+ return false;
+ }
+
+ compileTree(root);
+
+ if(!isError()) {
+ out->dumpPre();
+ } else {
+ reset(out, true);
+ }
+
+ output = 0;
+ return !isError();
+}
+
+void QmlCompiler::compileTree(Object *tree)
+{
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.line = 0;
+ init.init.dataSize = 0;
+ output->bytecode << init;
+
+ if(!compileObject(tree, 0)) // Compile failed
+ return;
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ optimizeExpressions(0, output->bytecode.count() - 1, 0);
+}
+
+bool QmlCompiler::compileObject(Object *obj, int ctxt)
+{
+ if(obj->type != -1) {
+ obj->metatype =
+ QmlMetaType::metaObjectForType(output->types.at(obj->type).className);
+ }
+
+ if(output->types.at(obj->type).className == "Component") {
+ COMPILE_CHECK(compileComponent(obj, ctxt));
+ return true;
+ }
+
+ ctxt = 0;
+
+ // Only use magical "properties" and "signals" properties if the type
+ // doesn't have already have them
+ bool ignoreProperties = false;
+ bool ignoreSignals = false;
+ if(obj->metatype && obj->metatype->indexOfProperty(PROPERTIES_NAME) != -1)
+ ignoreProperties = true;
+ if(obj->metatype && obj->metatype->indexOfProperty(SIGNALS_NAME) != -1)
+ ignoreSignals = true;
+
+ Property *propertiesProperty = ignoreProperties?0:obj->getProperty(PROPERTIES_NAME, false);
+ Property *signalsProperty = ignoreSignals?0:obj->getProperty(SIGNALS_NAME, false);
+
+ if(propertiesProperty) {
+ obj->dynamicPropertiesProperty = propertiesProperty;
+ obj->properties.remove(PROPERTIES_NAME);
+ }
+ if(signalsProperty) {
+ obj->dynamicSignalsProperty = signalsProperty;
+ obj->properties.remove(SIGNALS_NAME);
+ }
+
+ if(obj->type != -1 && output->types.at(obj->type).parser) {
+ QByteArray data = obj->custom;
+ int ref = output->indexForByteArray(data);
+
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateCustomObject;
+ create.line = obj->line;
+ create.createCustom.type = obj->type;
+ create.createCustom.data = ref;
+ output->bytecode << create;
+ } else {
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->line;
+ create.create.type = obj->type;
+ output->bytecode << create;
+ }
+
+ COMPILE_CHECK(compileDynamicPropertiesAndSignals(obj));
+
+ if(obj->type != -1) {
+ if(output->types.at(obj->type).component) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::TryBeginObject;
+ begin.line = obj->line;
+ output->bytecode << begin;
+ } else {
+ int cast = QmlMetaType::qmlParserStatusCast(QmlMetaType::type(output->types.at(obj->type).className));
+ if(cast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = cast;
+ begin.line = obj->line;
+ output->bytecode << begin;
+ }
+ }
+ }
+
+ foreach(Property *prop, obj->properties) {
+ if(!ignoreProperties && prop->name == PROPERTIES_NAME) {
+ } else if(!ignoreSignals && prop->name == SIGNALS_NAME) {
+ } else if(prop->name.length() >= 3 && prop->name.startsWith("on") &&
+ ('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) {
+ COMPILE_CHECK(compileSignal(prop, obj));
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+ }
+
+ if(obj->defaultProperty)
+ COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+
+ if(obj->type != -1) {
+ if(output->types.at(obj->type).component) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::TryCompleteObject;
+ complete.line = obj->line;
+ output->bytecode << complete;
+ } else {
+ int cast = QmlMetaType::qmlParserStatusCast(QmlMetaType::type(output->types.at(obj->type).className));
+ if(cast != -1) {
+ QmlInstruction complete;
+ complete.type = QmlInstruction::CompleteObject;
+ complete.complete.castValue = cast;
+ complete.line = obj->line;
+ output->bytecode << complete;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponent(Object *obj, int ctxt)
+{
+ Property *idProp = 0;
+ if(obj->properties.count() > 1 ||
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ COMPILE_EXCEPTION("Invalid component specification");
+ if(obj->defaultProperty &&
+ (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
+ (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
+ COMPILE_EXCEPTION("Invalid component body specification");
+ if(obj->properties.count())
+ idProp = *obj->properties.begin();
+ if(idProp && (idProp->value || idProp->values.count() > 1))
+ COMPILE_EXCEPTION("Invalid component id specification");
+
+ Object *root = 0;
+ if(obj->defaultProperty && obj->defaultProperty->values.count())
+ root = obj->defaultProperty->values.first()->object;
+
+ COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
+
+ if(idProp && idProp->values.count()) {
+ QString val = idProp->values.at(0)->primitive;
+ if(!isValidId(val))
+ COMPILE_EXCEPTION("Invalid id property value");
+
+ if(ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+ ids.insert(val);
+
+ int pref = output->indexForString(val);
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = idProp->line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+ output->bytecode << id;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
+{
+ output->bytecode.push_back(QmlInstruction());
+ QmlInstruction &create = output->bytecode.last();
+ create.type = QmlInstruction::CreateComponent;
+ create.line = obj->line;
+ int count = output->bytecode.count();
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.dataSize = 0;
+ init.line = obj->line;
+ output->bytecode << init;
+
+ QSet<QString> oldIds = ids;
+ ids.clear();
+ if(obj)
+ COMPILE_CHECK(compileObject(obj, ctxt));
+ ids = oldIds;
+
+ create.createComponent.count = output->bytecode.count() - count;
+
+ int inc = optimizeExpressions(count, count - 1 + create.createComponent.count, count);
+ create.createComponent.count += inc;
+ return true;
+}
+
+
+bool QmlCompiler::compileFetchedObject(Object *obj, int ctxt)
+{
+ if(obj->defaultProperty)
+ COMPILE_CHECK(compileProperty(obj->defaultProperty, obj, ctxt));
+
+ foreach(Property *prop, obj->properties) {
+ if(prop->name.length() >= 3 && prop->name.startsWith("on") &&
+ ('A' <= prop->name.at(2) && 'Z' >= prop->name.at(2))) {
+ COMPILE_CHECK(compileSignal(prop, obj));
+ } else {
+ COMPILE_CHECK(compileProperty(prop, obj, ctxt));
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileSignal(Property *prop, Object *obj)
+{
+ if(prop->values.isEmpty() && !prop->value)
+ return true;
+
+ if(prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION("Incorrectly specified signal");
+
+ if(prop->values.at(0)->object) {
+ int pr = output->indexForByteArray(prop->name);
+
+ bool rv = compileObject(prop->values.at(0)->object, 0);
+
+ if(rv) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = prop->values.at(0)->line;
+ assign.assignSignalObject.signal = pr;
+
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::SignalObject;
+ }
+
+ return rv;
+
+ } else {
+ QString script = prop->values.at(0)->primitive.trimmed();
+ if(script.isEmpty())
+ return true;
+
+ if(isBinding(script))
+ COMPILE_EXCEPTION("Cannot assign binding to signal property");
+
+ int idx = output->indexForString(script);
+ int pr = output->indexForByteArray(prop->name);
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignal;
+ assign.line = prop->values.at(0)->line;
+ assign.assignSignal.signal = pr;
+ assign.assignSignal.value = idx;
+
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::SignalExpression;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileProperty(Property *prop, Object *obj, int ctxt)
+{
+ if(prop->values.isEmpty() && !prop->value)
+ return true;
+
+ // First we're going to need a reference to this property
+ if(obj->type != -1) {
+
+ const QMetaObject *mo = obj->metaObject();
+ if(mo) {
+ if(prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ // XXX
+ // Currently we don't handle enums in the static analysis
+ // so we let them drop through to generateStoreInstruction()
+ if(p.name() && !p.isEnumType()) {
+ prop->index = mo->indexOfProperty(p.name());
+ prop->name = p.name();
+
+ int t = p.type();
+ if(t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ } else {
+ prop->index = mo->indexOfProperty(prop->name.constData());
+ QMetaProperty p = mo->property(prop->index);
+ // XXX
+ // Currently we don't handle enums in the static analysis
+ // so we let them drop through to generateStoreInstruction()
+ if(p.name() && !p.isEnumType()) {
+ int t = p.type();
+ if(t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ }
+ }
+ } else {
+ const QMetaObject *mo = obj->metaObject();
+ if(mo) {
+ if(prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ if(p.name()) {
+ prop->index = mo->indexOfProperty(p.name());
+ prop->name = p.name();
+ }
+ int t = p.type();
+ if(t == QVariant::UserType)
+ t = p.userType();
+ prop->type = t;
+ } else {
+ prop->index = mo->indexOfProperty(prop->name.constData());
+ QMetaProperty p = mo->property(prop->index);
+ int t = p.type();
+ if(t == QVariant::UserType)
+ t = p.userType();
+ prop->type = t;
+ }
+ }
+ }
+
+ if(prop->name == "id") {
+
+ COMPILE_CHECK(compileIdProperty(prop, obj));
+
+ } else if(isAttachedProperty(prop->name)) {
+
+ COMPILE_CHECK(compileAttachedProperty(prop, obj, ctxt));
+
+ } else if(prop->value) {
+
+ COMPILE_CHECK(compileNestedProperty(prop, ctxt));
+
+ } else if(QmlMetaType::isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+
+ COMPILE_CHECK(compileListProperty(prop, obj, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyAssignment(prop, obj, ctxt));
+
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if(prop->value)
+ COMPILE_EXCEPTION("The 'id' property cannot be fetched");
+ if(prop->values.count() > 1)
+ COMPILE_EXCEPTION("The 'id' property cannot be multiset");
+
+ if(prop->values.count() == 1) {
+ if(prop->values.at(0)->object)
+ COMPILE_EXCEPTION("Cannot assign an object as an id");
+ QString val = prop->values.at(0)->primitive;
+ if(!isValidId(val))
+ COMPILE_EXCEPTION(val << "is not a valid id");
+ if(ids.contains(val))
+ COMPILE_EXCEPTION("id is not unique");
+ ids.insert(val);
+
+ int pref = output->indexForString(val);
+
+ if(prop->type == QVariant::String) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreString;
+ assign.storeString.propertyIndex = prop->index;
+ assign.storeString.value = pref;
+ assign.line = prop->values.at(0)->line;
+ output->bytecode << assign;
+
+ prop->values.at(0)->type = Value::Id;
+ } else {
+ prop->values.at(0)->type = Value::Literal;
+ }
+
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = prop->values.at(0)->line;
+ id.setId.value = pref;
+ id.setId.save = -1;
+ id.line = prop->values.at(0)->line;
+ output->bytecode << id;
+
+ obj->id = val.toLatin1();
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ if(!prop->value)
+ COMPILE_EXCEPTION("Incorrect usage of an attached property");
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->line;
+ int ref = output->indexForByteArray(prop->name);
+ fetch.fetchAttached.idx = ref;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+bool QmlCompiler::compileNestedProperty(QmlParser::Property *prop,
+ int ctxt)
+{
+ if(prop->type != 0)
+ prop->value->metatype = QmlMetaType::metaObjectForType(prop->type);
+
+ QmlInstruction fetch;
+ if(prop->index != -1 &&
+ QmlMetaType::isObject(prop->value->metatype)) {
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.fetch.isObject = true;
+ } else {
+ fetch.type = QmlInstruction::ResolveFetchObject;
+ fetch.fetch.property = output->indexForByteArray(prop->name);
+ }
+ fetch.line = prop->line;
+ output->bytecode << fetch;
+
+ COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1));
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->line;
+ output->bytecode << pop;
+
+ return true;
+}
+
+bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ int t = prop->type;
+ if(QmlMetaType::isQmlList(t)) {
+ QmlInstruction fetch;
+ fetch.line = prop->line;
+ fetch.type = QmlInstruction::FetchQmlList;
+ fetch.fetchQmlList.property = prop->index;
+ fetch.fetchQmlList.type = QmlMetaType::qmlListType(t);
+ output->bytecode << fetch;
+
+ for(int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if(v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->line;
+ output->bytecode << pop;
+ } else {
+ Q_ASSERT(QmlMetaType::isList(t));
+
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchQList;
+ fetch.line = prop->line;
+ fetch.fetch.property = prop->index;
+ output->bytecode << fetch;
+
+ bool assignedBinding = false;
+ for(int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if(v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = v->line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+ } else if(isBinding(v->primitive)) {
+ if(assignedBinding)
+ COMPILE_EXCEPTION("Can only assign one binding to lists");
+
+ compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->line);
+ v->type = Value::PropertyBinding;
+ } else {
+ COMPILE_EXCEPTION("Cannot assign primitives to lists");
+ }
+ }
+
+ QmlInstruction pop;
+ pop.line = prop->line;
+ pop.type = QmlInstruction::PopQList;
+ output->bytecode << pop;
+ }
+ return true;
+}
+
+bool QmlCompiler::compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt)
+{
+ for(int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if(v->object) {
+
+ COMPILE_CHECK(compilePropertyObjectAssignment(prop, obj, v, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(compilePropertyLiteralAssignment(prop, obj, v, ctxt));
+
+ }
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ if(v->object->type != -1)
+ v->object->metatype = QmlMetaType::metaObjectForType(output->types.at(v->object->type).className);
+
+ if(v->object->metaObject()) {
+
+ const QMetaObject *propmo =
+ QmlMetaType::rawMetaObjectForType(prop->type);
+
+ bool isPropertyValue = false;
+ bool isAssignable = false;
+
+ if(propmo) {
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions
+ const QMetaObject *c = v->object->metatype;
+ while(propmo && c) {
+ isPropertyValue = isPropertyValue || (c == &QmlPropertyValueSource::staticMetaObject);
+ isAssignable = isAssignable || (c == propmo);
+ c = c->superClass();
+ }
+ } else {
+ const QMetaObject *c = v->object->metatype;
+ while(!isPropertyValue && c) {
+ isPropertyValue = c == &QmlPropertyValueSource::staticMetaObject;
+ c = c->superClass();
+ }
+ }
+
+ if(!propmo && !isPropertyValue) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObject;
+ assign.line = v->object->line;
+ assign.assignObject.castValue = 0;
+ if(prop->isDefault)
+ assign.assignObject.property = -1;
+ else
+ assign.assignObject.property =
+ output->indexForByteArray(prop->name);
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else if(isAssignable) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->line;
+ assign.storeObject.propertyIndex = prop->index;
+ // XXX - this cast may not be 0
+ assign.storeObject.cast = 0;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ } else if(propmo == &QmlComponent::staticMetaObject) {
+
+ COMPILE_CHECK(compileComponentFromRoot(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreObject;
+ assign.line = v->object->line;
+ assign.storeObject.propertyIndex = prop->index;
+ // XXX - this cast may not be 0
+ assign.storeObject.cast = 0;
+ output->bytecode << assign;
+
+ v->type = Value::Component;
+ } else if(isPropertyValue) {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ if (prop->index != -1) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::StoreValueSource;
+ assign.line = v->object->line;
+ assign.assignValueSource.property = prop->index;
+ output->bytecode << assign;
+ } else {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignValueSource;
+ assign.line = v->object->line;
+ assign.assignValueSource.property = output->indexForByteArray(prop->name);;
+ output->bytecode << assign;
+ }
+
+ v->type = Value::ValueSource;
+ } else {
+ COMPILE_EXCEPTION("Unassignable object");
+ }
+
+ } else {
+ COMPILE_CHECK(compileObject(v->object, ctxt));
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObject;
+ assign.line = v->object->line;
+ assign.assignObject.property = output->indexForByteArray(prop->name);
+ assign.assignObject.castValue = 0;
+ output->bytecode << assign;
+
+ v->type = Value::CreatedObject;
+ }
+
+ return true;
+}
+
+bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ int ctxt)
+{
+ if(isBinding(v->primitive)) {
+
+ compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->line);
+
+ v->type = Value::PropertyBinding;
+
+ } else {
+
+ QmlInstruction assign;
+ assign.line = v->line;
+
+ bool doassign = true;
+ if(prop->index != -1) {
+ StoreInstructionResult r =
+ generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &v->primitive);
+
+ if(r == Ok) {
+ doassign = false;
+ } else if(r == InvalidData) {
+ //### we are restricted to a rather generic message here. If we can find a way to move
+ // the exception into generateStoreInstruction we could potentially have better messages.
+ // (the problem is that both compile and run exceptions can be generated, though)
+ COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name());
+ doassign = false;
+ } else if(r == ReadOnly) {
+ COMPILE_EXCEPTION("Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name());
+ } else {
+ doassign = true;
+ }
+ }
+
+ if(doassign) {
+ assign.type = QmlInstruction::AssignConstant;
+ if(prop->isDefault) {
+ assign.assignConstant.property = -1;
+ } else {
+ assign.assignConstant.property =
+ output->indexForByteArray(prop->name);
+ }
+ assign.assignConstant.constant =
+ output->indexForString(v->primitive);
+ }
+
+ output->bytecode << assign;
+
+ v->type = Value::Literal;
+ }
+ return true;
+}
+
+bool QmlCompiler::findDynamicProperties(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ QList<Object::DynamicProperty> definedProperties;
+
+ struct TypeNameToType {
+ const char *name;
+ Object::DynamicProperty::Type type;
+ } propTypeNameToTypes[] = {
+ { "", Object::DynamicProperty::Variant },
+ { "int", Object::DynamicProperty::Int },
+ { "bool", Object::DynamicProperty::Bool },
+ { "double", Object::DynamicProperty::Real },
+ { "real", Object::DynamicProperty::Real },
+ { "string", Object::DynamicProperty::String },
+ { "color", Object::DynamicProperty::Color },
+ { "date", Object::DynamicProperty::Date },
+ { "variant", Object::DynamicProperty::Variant }
+ };
+ const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
+ sizeof(propTypeNameToTypes[0]);
+
+
+ if(prop->value)
+ COMPILE_EXCEPTION("Invalid property specification");
+
+ bool seenDefault = false;
+ for(int ii = 0; ii < prop->values.count(); ++ii) {
+ QmlParser::Value *val = prop->values.at(ii);
+ if(!val->object)
+ COMPILE_EXCEPTION("Invalid property specification");
+
+ QmlParser::Object *obj = val->object;
+ if(obj->type == -1 || output->types.at(obj->type).className != "Property")
+ COMPILE_EXCEPTION("Use Property tag to specify properties");
+
+
+ enum Seen { None = 0, Name = 0x01,
+ Type = 0x02, Value = 0x04,
+ ValueChanged = 0x08,
+ Default = 0x10 } seen = None;
+
+ Object::DynamicProperty propDef;
+
+ for(QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ obj->properties.begin();
+ iter != obj->properties.end();
+ ++iter) {
+
+ QmlParser::Property *property = *iter;
+ if(property->name == "name") {
+ if (seen & Name)
+ COMPILE_EXCEPTION("May only specify Property name once");
+ seen = (Seen)(seen | Name);
+
+ if(property->value || property->values.count() != 1 ||
+ property->values.at(0)->object)
+ COMPILE_EXCEPTION("Invalid Property name");
+
+ propDef.name = property->values.at(0)->primitive.toLatin1();
+
+ } else if(property->name == "type") {
+ if (seen & Type)
+ COMPILE_EXCEPTION("May only specify Property type once");
+ seen = (Seen)(seen | Type);
+
+ if(property->value || property->values.count() != 1 ||
+ property->values.at(0)->object)
+ COMPILE_EXCEPTION("Invalid Property type");
+
+ QString type = property->values.at(0)->primitive.toLower();
+ bool found = false;
+ for(int ii = 0; !found && ii < propTypeNameToTypesCount; ++ii) {
+ if(type == QLatin1String(propTypeNameToTypes[ii].name)){
+ found = true;
+ propDef.type = propTypeNameToTypes[ii].type;
+ }
+
+ }
+
+ if(!found)
+ COMPILE_EXCEPTION("Invalid Property type");
+
+ } else if(property->name == "value") {
+ if (seen & Value)
+ COMPILE_EXCEPTION("May only specify Property value once");
+ seen = (Seen)(seen | Value);
+
+ propDef.defaultValue = property;
+ } else if(property->name == "onValueChanged") {
+ if (seen & ValueChanged)
+ COMPILE_EXCEPTION("May only specify Property onValueChanged once");
+ seen = (Seen)(seen | ValueChanged);
+
+ if(property->value || property->values.count() != 1 ||
+ property->values.at(0)->object)
+ COMPILE_EXCEPTION("Invalid Property onValueChanged");
+
+ propDef.onValueChanged = property->values.at(0)->primitive;
+
+ } else if(property->name == "default") {
+ if(seen & Default)
+ COMPILE_EXCEPTION("May only specify Property default once");
+ seen = (Seen)(seen | Default);
+ if(property->value || property->values.count() != 1 ||
+ property->values.at(0)->object)
+ COMPILE_EXCEPTION("Invalid Property default");
+
+ bool defaultValue =
+ QmlStringConverters::boolFromString(property->values.at(0)->primitive);
+ propDef.isDefaultProperty = defaultValue;
+ if(defaultValue) {
+ if(seenDefault)
+ COMPILE_EXCEPTION("Only one property may be the default");
+ seenDefault = true;
+ }
+
+ } else {
+ COMPILE_EXCEPTION("Invalid Property property");
+ }
+
+ }
+ if(obj->defaultProperty) {
+ if(seen & Value)
+ COMPILE_EXCEPTION("May only specify Property value once");
+
+ seen = (Seen)(seen | Value);
+ propDef.defaultValue = obj->defaultProperty;
+ }
+
+ if(!(seen & Name))
+ COMPILE_EXCEPTION("Must specify Property name");
+
+ definedProperties << propDef;
+ }
+
+ obj->dynamicProperties = definedProperties;
+ return true;
+}
+
+bool QmlCompiler::findDynamicSignals(QmlParser::Property *sigs,
+ QmlParser::Object *obj)
+{
+ QList<Object::DynamicSignal> definedSignals;
+
+ if(sigs->value)
+ COMPILE_EXCEPTION("Invalid signal specification");
+
+ for(int ii = 0; ii < sigs->values.count(); ++ii) {
+ QmlParser::Value *val = sigs->values.at(ii);
+ if(!val->object)
+ COMPILE_EXCEPTION("Invalid signal specification");
+
+ QmlParser::Object *obj = val->object;
+ if(obj->type == -1 || output->types.at(obj->type).className != "Signal")
+ COMPILE_EXCEPTION("Use Signal tag to specify signals");
+
+ enum Seen { None = 0, Name = 0x01 } seen = None;
+ Object::DynamicSignal sigDef;
+
+ for(QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ obj->properties.begin();
+ iter != obj->properties.end();
+ ++iter) {
+
+ QmlParser::Property *property = *iter;
+ if(property->name == "name") {
+ if (seen & Name)
+ COMPILE_EXCEPTION("May only specify Signal name once");
+ seen = (Seen)(seen | Name);
+
+ if(property->value || property->values.count() != 1 ||
+ property->values.at(0)->object)
+ COMPILE_EXCEPTION("Invalid Signal name");
+
+ sigDef.name = property->values.at(0)->primitive.toLatin1();
+
+ } else {
+ COMPILE_EXCEPTION("Invalid Signal property");
+ }
+
+ }
+
+ if(obj->defaultProperty)
+ COMPILE_EXCEPTION("Invalid Signal property");
+
+ if(!(seen & Name))
+ COMPILE_EXCEPTION("Must specify Signal name");
+
+ definedSignals << sigDef;
+ }
+
+ obj->dynamicSignals = definedSignals;
+ return true;
+}
+
+bool QmlCompiler::compileDynamicPropertiesAndSignals(QmlParser::Object *obj)
+{
+ if(obj->dynamicPropertiesProperty)
+ findDynamicProperties(obj->dynamicPropertiesProperty, obj);
+ if(obj->dynamicSignalsProperty)
+ findDynamicSignals(obj->dynamicSignalsProperty, obj);
+
+ if(obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty())
+ return true;
+
+ QMetaObjectBuilder builder;
+ if(obj->metatype)
+ builder.setClassName(QByteArray(obj->metatype->className()) + "QML");
+
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ for(int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if(p.isDefaultProperty)
+ builder.addClassInfo("DefaultProperty", p.name);
+
+ QByteArray type;
+ switch(p.type) {
+ case Object::DynamicProperty::Variant:
+ type = "QVariant";
+ break;
+ case Object::DynamicProperty::Int:
+ type = "int";
+ break;
+ case Object::DynamicProperty::Bool:
+ type = "bool";
+ break;
+ case Object::DynamicProperty::Real:
+ type = "double";
+ break;
+ case Object::DynamicProperty::String:
+ type = "QString";
+ break;
+ case Object::DynamicProperty::Color:
+ type = "QColor";
+ break;
+ case Object::DynamicProperty::Date:
+ type = "QDate";
+ break;
+ }
+
+ builder.addSignal("qml__" + QByteArray::number(ii) + "()");
+ builder.addProperty(p.name, type, ii);
+ }
+
+ for(int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
+ builder.addSignal(s.name + "()");
+ }
+
+ if(obj->metatype)
+ builder.setSuperClass(obj->metatype);
+
+ obj->extObject = builder.toMetaObject();
+
+ output->mos << obj->extObject;
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreMetaObject;
+ store.storeMeta.data = output->mos.count() - 1;
+ store.line = obj->line;
+ output->bytecode << store;
+
+ for(int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if(p.defaultValue) {
+ p.defaultValue->name = p.name;
+ p.defaultValue->isDefault = false;
+ COMPILE_CHECK(compileProperty(p.defaultValue, obj, 0));
+ }
+
+ if(!p.onValueChanged.isEmpty()) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignal;
+ assign.line = obj->line;
+ assign.assignSignal.signal =
+ output->indexForByteArray("onQml__" + QByteArray::number(ii));
+ assign.assignSignal.value =
+ output->indexForString(p.onValueChanged);
+ output->bytecode << assign;
+ }
+ }
+
+ return true;
+}
+
+void QmlCompiler::compileBinding(const QString &str, QmlParser::Property *prop,
+ int ctxt, const QMetaObject *mo, qint64 line)
+{
+ Q_ASSERT(isBinding(str));
+
+ QString bind = str.mid(1, str.length() - 2).trimmed();
+ QmlBasicScript bs;
+ bs.compile(bind.toLatin1());
+
+ int bref;
+ if(bs.isValid()) {
+ bref = output->indexForByteArray(QByteArray(bs.compileData(), bs.compileDataSize()));
+ } else {
+ bref = output->indexForString(bind);
+ }
+
+ QmlInstruction assign;
+ assign.assignBinding.context = ctxt;
+ assign.line = line;
+ if(prop->index != -1) {
+ if(bs.isValid())
+ assign.type = QmlInstruction::StoreCompiledBinding;
+ else
+ assign.type = QmlInstruction::StoreBinding;
+
+ assign.assignBinding.property = prop->index;
+ assign.assignBinding.value = bref;
+ assign.assignBinding.category = QmlMetaProperty::Unknown;
+ if(mo) {
+ //XXX we should generate an exception if the property is read-only
+ QMetaProperty mp = mo->property(assign.assignBinding.property);
+ assign.assignBinding.category = QmlMetaProperty::propertyCategory(mp);
+ }
+ } else {
+ if(bs.isValid())
+ assign.type = QmlInstruction::AssignCompiledBinding;
+ else
+ assign.type = QmlInstruction::AssignBinding;
+ assign.assignBinding.property = output->indexForByteArray(prop->name);
+ assign.assignBinding.value = bref;
+ assign.assignBinding.category = QmlMetaProperty::Unknown;
+ }
+ output->bytecode << assign;
+}
+
+int QmlCompiler::optimizeExpressions(int start, int end, int patch)
+{
+ QHash<QString, int> ids;
+ int saveCount = 0;
+ int newInstrs = 0;
+
+ for(int ii = start; ii <= end; ++ii) {
+ const QmlInstruction &instr = output->bytecode.at(ii);
+
+ if(instr.type == QmlInstruction::CreateComponent) {
+ ii += instr.createComponent.count - 1;
+ continue;
+ }
+
+ if(instr.type == QmlInstruction::SetId) {
+ QString id = output->primitives.at(instr.setId.value);
+ ids.insert(id, ii);
+ }
+ }
+
+ for(int ii = start; ii <= end; ++ii) {
+ const QmlInstruction &instr = output->bytecode.at(ii);
+
+ if(instr.type == QmlInstruction::CreateComponent) {
+ ii += instr.createComponent.count - 1;
+ continue;
+ }
+
+ if(instr.type == QmlInstruction::StoreCompiledBinding) {
+ QmlBasicScript s(output->datas.at(instr.assignBinding.value).constData());
+
+ if(s.isSingleLoad()) {
+ QString slt = QLatin1String(s.singleLoadTarget());
+ if(!slt.at(0).isUpper())
+ continue;
+
+ if(ids.contains(slt) &&
+ instr.assignBinding.category == QmlMetaProperty::Object) {
+ int id = ids[slt];
+ int saveId = -1;
+
+ if(output->bytecode.at(id).setId.save != -1) {
+ saveId = output->bytecode.at(id).setId.save;
+ } else {
+ output->bytecode[id].setId.save = saveCount;
+ saveId = saveCount;
+ ++saveCount;
+ }
+
+ int prop = instr.assignBinding.property;
+
+ QmlInstruction &rwinstr = output->bytecode[ii];
+ rwinstr.type = QmlInstruction::PushProperty;
+ rwinstr.pushProperty.property = prop;
+
+ QmlInstruction instr;
+ instr.type = QmlInstruction::AssignStackObject;
+ instr.line = 0;
+ instr.assignStackObject.property = newInstrs;
+ instr.assignStackObject.object = saveId;
+ output->bytecode << instr;
+ ++newInstrs;
+ }
+ }
+ }
+
+ }
+
+ if(saveCount)
+ output->bytecode[patch].init.dataSize = saveCount;
+
+ return newInstrs;
+}
+
+QmlCompiledData::QmlCompiledData()
+{
+}
+
+QmlCompiledData::QmlCompiledData(const QmlCompiledData &other)
+{
+ *this = other;
+}
+
+QmlCompiledData::~QmlCompiledData()
+{
+ for(int ii = 0; ii < types.count(); ++ii) {
+ if(types.at(ii).ref)
+ types.at(ii).ref->release();
+ }
+}
+
+QmlCompiledData &QmlCompiledData::operator=(const QmlCompiledData &other)
+{
+ types = other.types;
+ primitives = other.primitives;
+ floatData = other.floatData;
+ intData = other.intData;
+ customTypeData = other.customTypeData;
+ datas = other.datas;
+ mos = other.mos;
+ bytecode = other.bytecode;
+ return *this;
+}
+
+QObject *QmlCompiledData::TypeReference::createInstance() const
+{
+ if(type) {
+ return type->create();
+ } else if(component) {
+ return component->create(QmlContext::activeContext());
+ } else {
+ return 0;
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
new file mode 100644
index 0000000..732d9ea
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 QMLCOMPILER_P_H
+#define QMLCOMPILER_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qset.h>
+#include <qml.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+class QStringList;
+
+QT_BEGIN_NAMESPACE
+class QmlXmlParser;
+class QmlEngine;
+class QmlComponent;
+class QmlCompiledComponent;
+
+namespace QmlParser {
+ class Object;
+ class Property;
+ class Value;
+};
+
+class QmlCompiledData
+{
+public:
+ QmlCompiledData();
+ QmlCompiledData(const QmlCompiledData &other);
+ QmlCompiledData &operator=(const QmlCompiledData &other);
+ virtual ~QmlCompiledData();
+
+ QByteArray name;
+ QUrl url;
+
+ struct TypeReference
+ {
+ TypeReference()
+ : type(0), component(0), parser(0), ref(0) {}
+
+ QByteArray className;
+ QmlType *type;
+ QmlComponent *component;
+ QmlCustomParser *parser;
+
+ QmlRefCount *ref;
+ QObject *createInstance() const;
+ };
+ QList<TypeReference> types;
+ struct CustomTypeData
+ {
+ int index;
+ int type;
+ };
+ QList<QString> primitives;
+ QList<float> floatData;
+ QList<int> intData;
+ QList<CustomTypeData> customTypeData;
+ QList<QByteArray> datas;
+ QList<QMetaObject *> mos;
+ QList<QmlInstruction> bytecode;
+
+private:
+ friend class QmlCompiler;
+ int indexForString(const QString &);
+ int indexForByteArray(const QByteArray &);
+ int indexForFloat(float *, int);
+ int indexForInt(int *, int);
+};
+
+class Q_DECLARATIVE_EXPORT QmlCompiler
+{
+public:
+ QmlCompiler();
+
+ bool compile(QmlEngine *, QmlCompositeTypeManager::TypeData *, QmlCompiledComponent *);
+
+ bool isError() const;
+ qint64 errorLine() const;
+ QString errorDescription() const;
+
+ static bool isValidId(const QString &);
+ static bool isBinding(const QString &);
+ static bool isAttachedProperty(const QByteArray &);
+
+ enum StoreInstructionResult { Ok, UnknownType, InvalidData, ReadOnly };
+ static StoreInstructionResult
+ generateStoreInstruction(QmlCompiledData &data,
+ QmlInstruction &instr,
+ const QMetaProperty &prop,
+ int index,
+ int primitive,
+ const QString *string);
+private:
+ void reset(QmlCompiledComponent *, bool);
+
+ void compileTree(QmlParser::Object *tree);
+ bool compileObject(QmlParser::Object *obj, int);
+ bool compileComponent(QmlParser::Object *obj, int);
+ bool compileComponentFromRoot(QmlParser::Object *obj, int);
+ bool compileFetchedObject(QmlParser::Object *obj, int);
+ bool compileSignal(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool compileProperty(QmlParser::Property *prop, QmlParser::Object *obj, int);
+ bool compileIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj);
+ bool compileAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compileNestedProperty(QmlParser::Property *prop,
+ int ctxt);
+ bool compileListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ int ctxt);
+ bool compilePropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ int ctxt);
+ bool compilePropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ int ctxt);
+
+ bool findDynamicProperties(QmlParser::Property *prop,
+ QmlParser::Object *obj);
+ bool findDynamicSignals(QmlParser::Property *sigs,
+ QmlParser::Object *obj);
+
+ bool compileDynamicPropertiesAndSignals(QmlParser::Object *obj);
+ void compileBinding(const QString &, QmlParser::Property *prop,
+ int ctxt, const QMetaObject *, qint64);
+
+ int optimizeExpressions(int start, int end, int patch = -1);
+
+ QSet<QString> ids;
+ qint64 exceptionLine;
+ QString exceptionDescription;
+ QmlCompiledData *output;
+};
+
+QT_END_NAMESPACE
+#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
new file mode 100644
index 0000000..c863a00
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** 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 "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "private/qmlcontext_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include <QStack>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlengine.h>
+#include <QFileInfo>
+#include <qmlbindablevalue.h>
+#include "private/qmlxmlparser_p.h"
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/qdebug.h>
+#include <QApplication>
+
+
+QT_BEGIN_NAMESPACE
+class QByteArray;
+
+/*!
+ \class QmlComponent
+ \brief The QmlComponent class encapsulates a QML component description.
+ \mainclass
+*/
+QML_DEFINE_TYPE(QmlComponent,Component);
+
+void QmlComponentPrivate::typeDataReady()
+{
+ Q_Q(QmlComponent);
+
+ Q_ASSERT(typeData);
+
+ fromTypeData(typeData);
+ typeData = 0;
+
+ emit q->readyChanged();
+}
+
+void QmlComponentPrivate::fromTypeData(QmlCompositeTypeManager::TypeData *data)
+{
+ name = data->url;
+ QmlCompiledComponent *c = data->toCompiledComponent(engine);
+
+ if(!c) {
+ Q_ASSERT(data->status == QmlCompositeTypeManager::TypeData::Error);
+
+ qWarning().nospace() << "QmlComponent: "
+ << data->errorDescription.toLatin1().constData();
+ } else {
+
+ cc = c;
+
+ }
+
+ data->release();
+}
+
+/*!
+ Construct a null QmlComponent.
+*/
+QmlComponent::QmlComponent(QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->name = QLatin1String("<unspecified file>");
+}
+
+/*!
+ Destruct the QmlComponent.
+*/
+QmlComponent::~QmlComponent()
+{
+ Q_D(QmlComponent);
+ if (d->typeData) {
+ d->typeData->remWaiter(d);
+ d->typeData->release();
+ }
+ if (d->cc)
+ d->cc->release();
+}
+
+/*!
+ \property QmlComponent::name
+ \brief the component's name.
+
+ The component's name is used in error and warning messages. If available,
+ the XML source file name is used as the component's name, otherwise it is
+ set to "<unspecified file>".
+*/
+QString QmlComponent::name() const
+{
+ Q_D(const QmlComponent);
+ return d->name;
+}
+
+void QmlComponent::setName(const QString &name)
+{
+ Q_D(QmlComponent);
+ d->name = name;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledComponent *cc, int start, int count, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->name = QLatin1String("<unspecified file>");
+ d->cc = cc;
+ cc->addref();
+ d->start = start;
+ d->count = count;
+}
+
+QmlComponent::QmlComponent(QmlEngine *engine, const QUrl &url, QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->name = url.toString();
+
+ QmlCompositeTypeManager::TypeData *data =
+ engine->d_func()->typeManager.get(url);
+
+ if(data->status == QmlCompositeTypeManager::TypeData::Waiting) {
+
+ d->typeData = data;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(data);
+
+ }
+}
+
+/*!
+ Create a QmlComponent with no data. Set setData().
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+}
+
+/*!
+ Create a QmlComponent from the given XML \a data. If provided, \a filename
+ is used to set the component name, and to provide a base path for items
+ resolved by this component.
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QByteArray &data, const QUrl &url, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ setData(data,url);
+}
+
+/*!
+ Sets the QmlComponent to use the given XML \a data. If provided, \a filename
+ is used to set the component name, and to provide a base path for items
+ resolved by this component.
+
+ Currently only supported to call once per component.
+*/
+void QmlComponent::setData(const QByteArray &data, const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ if(d->cc) d->cc->release();
+ if(d->typeData) d->typeData->release();
+ d->cc = 0;
+ d->typeData = 0;
+
+ d->name = url.toString();
+
+ QmlCompositeTypeManager::TypeData *typeData =
+ d->engine->d_func()->typeManager.getImmediate(data, url);
+
+ if(typeData->status == QmlCompositeTypeManager::TypeData::Waiting) {
+
+ d->typeData = typeData;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(typeData);
+
+ }
+
+}
+
+bool QmlComponent::isReady() const
+{
+ Q_D(const QmlComponent);
+
+ return d->engine && !d->typeData;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QmlComponent);
+ d->name = QLatin1String("<unspecified file>");
+ d->cc = new QmlCompiledComponent;
+}
+
+/*!
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ If \a context is 0 (the default), it will create the instance in the
+ engine' s \l {QmlEngine::rootContext()}{root context}.
+*/
+QObject *QmlComponent::create(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if(!context)
+ context = d->engine->rootContext();
+
+ if(context->engine() != d->engine) {
+ qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ QObject *rv = beginCreate(context);
+ completeCreate();
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ When QmlComponent constructs an instance, it occurs in three steps:
+ \list 1
+ \i The object hierarchy is created, and constant values are assigned.
+ \i Property bindings are evaluated for the the first time.
+ \i If applicable, QmlParserStatus::componentComplete() is called on objects.
+ \endlist
+ QmlComponent::beginCreate() differs from QmlComponent::create() in that it
+ only performs step 1. QmlComponent::completeCreate() must be called to
+ complete steps 2 and 3.
+
+ This breaking point is sometimes useful when using attached properties to
+ communicate information to an instantiated component, as it allows their
+ initial values to be configured before property bindings take effect.
+*/
+QObject *QmlComponent::beginCreate(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ if(!context) {
+ qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context");
+ return 0;
+ }
+
+ if(context->engine() != d->engine) {
+ qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ if (d->completePending) {
+ qWarning("QmlComponent: Cannot create new component instance before completing the previous");
+ return 0;
+ }
+ if (!d->cc) {
+ qWarning("QmlComponent: Cannot load component data");
+ return 0;
+ }
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CreateComponent> perf;
+#endif
+ if(!d->engine->d_func()->rootComponent)
+ d->engine->d_func()->rootComponent = this;
+
+ QmlContext *ctxt =
+ new QmlContext(context, 0);
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->component = d->cc;
+ static_cast<QmlContextPrivate*>(ctxt->d_ptr)->component->addref();
+ ctxt->activate();
+
+ QmlVME vme;
+ QObject *rv = vme.run(ctxt, d->cc, d->start, d->count);
+ if(vme.isError()) {
+ qWarning().nospace()
+#ifdef QML_VERBOSEERRORS_ENABLED
+ << "QmlComponent: "
+#endif
+ << vme.errorDescription().toLatin1().constData() << " @"
+ << d->name.toLatin1().constData() << ":" << vme.errorLine();
+ }
+
+
+ ctxt->deactivate();
+
+ if(rv) {
+ QFx_setParent_noEvent(ctxt, rv);
+ QmlEnginePrivate *ep = d->engine->d_func();
+ if(ep->rootComponent == this) {
+ ep->rootComponent = 0;
+
+ d->bindValues = ep->currentBindValues;
+ d->parserStatus = ep->currentParserStatus;
+ ep->currentBindValues.clear();
+ ep->currentParserStatus.clear();
+ d->completePending = true;
+ }
+ } else {
+ delete ctxt;
+ }
+
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Complete a component creation begin with QmlComponent::beginCreate().
+*/
+void QmlComponent::completeCreate()
+{
+ Q_D(QmlComponent);
+ if (d->completePending) {
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindInit> bi;
+#endif
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ d->bindValues.at(ii)->init();
+ }
+ QSet<QmlParserStatus *> done;
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii) {
+ QmlParserStatus *ps = d->parserStatus.at(ii);
+ if(!done.contains(ps)) {
+ done.insert(ps);
+ ps->componentComplete();
+ }
+ }
+
+ d->bindValues.clear();
+ d->parserStatus.clear();
+ d->completePending = false;
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
new file mode 100644
index 0000000..1a74fe9
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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 QMLCOMPONENT_H
+#define QMLCOMPONENT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlCompiledComponent;
+class QByteArray;
+class QmlComponentPrivate;
+class QmlEngine;
+class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponent);
+
+ Q_PROPERTY(QString name READ name WRITE setName);
+
+public:
+ QmlComponent(QObject *parent=0);
+ QmlComponent(QmlEngine *, QObject *parent=0);
+ QmlComponent(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QByteArray &, const QUrl &url=QUrl(), QObject *parent=0);
+ ~QmlComponent();
+
+ virtual QObject *create(QmlContext *context = 0);
+ virtual QObject *beginCreate(QmlContext *);
+ virtual void completeCreate();
+
+ QString name() const;
+ void setName(const QString &name);
+
+ void setData(const QByteArray &, const QUrl &url);
+
+ bool isReady() const;
+
+ QmlComponent(QmlEngine *, QmlCompiledComponent *, int, int, QObject *parent);
+
+Q_SIGNALS:
+ void readyChanged();
+
+protected:
+ QmlComponent(QmlComponentPrivate &dd, QObject* parent);
+
+private:
+ friend class QmlVME;
+};
+QML_DECLARE_TYPE(QmlComponent);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCOMPONENT_H
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
new file mode 100644
index 0000000..e97ec67
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QMLCOMPONENT_P_H
+#define QMLCOMPONENT_P_H
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include "private/qobject_p.h"
+#include "private/qmlcompositetypemanager_p.h"
+#include "qmlcomponent.h"
+class QmlComponent;
+class QmlEngine;
+class QmlCompiledComponent;
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponentPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponent)
+
+public:
+ QmlComponentPrivate() : typeData(0), start(-1), count(-1), cc(0), completePending(false), engine(0) {}
+
+ QmlCompositeTypeManager::TypeData *typeData;
+ void typeDataReady();
+
+ void fromTypeData(QmlCompositeTypeManager::TypeData *data);
+
+ QString name;
+
+ int start;
+ int count;
+ QmlCompiledComponent *cc;
+ QList<QmlBindableValue *> bindValues;
+ QList<QmlParserStatus *> parserStatus;
+ bool completePending;
+
+ QmlEngine *engine;
+};
+
+#endif // QMLCOMPONENT_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
new file mode 100644
index 0000000..65596ae
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** 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 <private/qmlcompositetypemanager_p.h>
+#include <private/qmlxmlparser_p.h>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlcomponent_p.h>
+
+QmlCompositeTypeManager::TypeData::TypeData()
+: status(Invalid), component(0), compiledComponent(0)
+{
+}
+
+QmlCompositeTypeManager::TypeData::~TypeData()
+{
+ for(int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+
+ if(compiledComponent)
+ compiledComponent->release();
+
+ if(component)
+ delete component;
+}
+
+void QmlCompositeTypeManager::TypeData::addWaiter(QmlComponentPrivate *p)
+{
+ waiters << p;
+}
+
+void QmlCompositeTypeManager::TypeData::remWaiter(QmlComponentPrivate *p)
+{
+ waiters.removeAll(p);
+}
+
+QmlComponent *QmlCompositeTypeManager::TypeData::toComponent(QmlEngine *engine)
+{
+ if(!component) {
+
+ QmlCompiledComponent *cc = toCompiledComponent(engine);
+ if(cc) {
+ component = new QmlComponent(engine, cc, -1, -1, 0);
+ } else {
+ component = new QmlComponent(engine, 0);
+ }
+
+ }
+
+ return component;
+}
+
+QmlCompiledComponent *
+QmlCompositeTypeManager::TypeData::toCompiledComponent(QmlEngine *engine)
+{
+ if(status == Complete && !compiledComponent) {
+
+ compiledComponent = new QmlCompiledComponent;
+ compiledComponent->url = QUrl(url);
+ compiledComponent->name = url.toLatin1(); // ###
+
+ QmlCompiler compiler;
+ if(!compiler.compile(engine, this, compiledComponent)) {
+ status = Error;
+ errorDescription = compiler.errorDescription() +
+ QLatin1String("@") +
+ url + QLatin1String(":") +
+ QString::number(compiler.errorLine());
+ compiledComponent->release();
+ compiledComponent = 0;
+ }
+
+ // Data is no longer needed once we have a compiled component
+ data.clear();
+ }
+
+ if(compiledComponent)
+ compiledComponent->addref();
+
+ return compiledComponent;
+}
+
+QmlCompositeTypeManager::TypeData::TypeReference::TypeReference()
+: type(0), unit(0), parser(0)
+{
+}
+
+QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlCompositeTypeManager::TypeData *QmlCompositeTypeManager::get(const QUrl &url)
+{
+ TypeData *unit = components.value(url.toString());
+
+ if(!unit) {
+ unit = new TypeData;
+ unit->status = TypeData::Waiting;
+ unit->url = url.toString();
+ components.insert(url.toString(), unit);
+
+ loadSource(unit);
+ }
+
+ unit->addref();
+ return unit;
+}
+
+QmlCompositeTypeManager::TypeData *
+QmlCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url)
+{
+ TypeData *unit = new TypeData;
+ unit->status = TypeData::Waiting;
+ unit->url = url.toString();
+ setData(unit, data, url);
+ return unit;
+}
+
+void QmlCompositeTypeManager::clearCache()
+{
+ for(Components::Iterator iter = components.begin(); iter != components.end();) {
+ if((*iter)->status != TypeData::Waiting) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+
+void QmlCompositeTypeManager::replyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ TypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ if(reply->error() != QNetworkReply::NoError) {
+
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("Network error for URL ") +
+ reply->url().toString();
+
+ unit->status = TypeData::Error;
+ unit->errorDescription = errorDescription;
+ doComplete(unit);
+
+ } else {
+ QByteArray data = reply->readAll();
+
+ setData(unit, data, reply->url());
+ }
+
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadSource(TypeData *unit)
+{
+ QUrl url(unit->url);
+
+ if(url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if(file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ setData(unit, data, url);
+ } else {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("File error for URL ") + url.toString();
+ unit->status = TypeData::Error;
+ unit->errorDescription = errorDescription;
+ doComplete(unit);
+ }
+
+ } else {
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ }
+}
+
+void QmlCompositeTypeManager::setData(TypeData *unit, const QByteArray &data,
+ const QUrl &url)
+{
+ if(!unit->data.parse(data, url)) {
+
+ unit->status = TypeData::Error;
+ unit->errorDescription = unit->data.errorDescription();
+ doComplete(unit);
+
+ } else {
+
+ engine->addNameSpacePaths(unit->data.nameSpacePaths());
+ compile(unit);
+
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(TypeData *unit)
+{
+ for(int ii = 0; ii < unit->dependants.count(); ++ii) {
+ checkComplete(unit->dependants.at(ii));
+ unit->dependants.at(ii)->release();
+ }
+ unit->dependants.clear();
+
+ while(!unit->waiters.isEmpty()) {
+ QmlComponentPrivate *p = unit->waiters.takeFirst();
+ p->typeDataReady();
+ }
+}
+
+void QmlCompositeTypeManager::checkComplete(TypeData *unit)
+{
+ if(unit->status != TypeData::Waiting)
+ return;
+
+ int waiting = 0;
+ for(int ii = 0; ii < unit->types.count(); ++ii) {
+ TypeData *u = unit->types.at(ii).unit;
+
+ if(!u)
+ continue;
+
+ if(u->status == TypeData::Error) {
+ unit->status = TypeData::Error;
+ unit->errorDescription = u->errorDescription;
+ doComplete(unit);
+ return;
+ } else if(u->status == TypeData::Waiting) {
+ waiting++;
+ }
+ }
+ if(!waiting) {
+ unit->status = TypeData::Complete;
+ doComplete(unit);
+ }
+}
+
+void QmlCompositeTypeManager::compile(TypeData *unit)
+{
+ QStringList typeNames = unit->data.types();
+
+ int waiting = 0;
+ for(int ii = 0; ii < typeNames.count(); ++ii) {
+ QByteArray type = typeNames.at(ii).toLatin1();
+
+ TypeData::TypeReference ref;
+ if (type == QByteArray("Property") ||
+ type == QByteArray("Signal")) {
+ unit->types << ref;
+ continue;
+ }
+
+ QmlCustomParser *parser =
+ QmlMetaType::customParser(type);
+
+ if(parser) {
+ ref.parser = parser;
+ unit->types << ref;
+ continue;
+ }
+
+ ref.type = QmlMetaType::qmlType(type);
+ if(ref.type) {
+ ref.parser = parser;
+ unit->types << ref;
+ continue;
+ }
+
+ QUrl url = engine->componentUrl(QUrl(type + ".qml"), QUrl(unit->url));
+ TypeData *urlUnit = components.value(url.toString());
+
+ if(!urlUnit) {
+ urlUnit = new TypeData;
+ urlUnit->status = TypeData::Waiting;
+ urlUnit->url = url.toString();
+ components.insert(url.toString(), urlUnit);
+
+ loadSource(urlUnit);
+ }
+
+ ref.unit = urlUnit;
+ switch(urlUnit->status) {
+ case TypeData::Invalid:
+ case TypeData::Error:
+ unit->status = TypeData::Error;
+ unit->errorDescription = urlUnit->errorDescription;
+ doComplete(unit);
+ return;
+
+ case TypeData::Complete:
+ break;
+
+ case TypeData::Waiting:
+ unit->addref();
+ ref.unit->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ unit->types << ref;
+ }
+
+ if(waiting) {
+ unit->status = TypeData::Waiting;
+ } else {
+ unit->status = TypeData::Complete;
+ doComplete(unit);
+ }
+}
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
new file mode 100644
index 0000000..6982844
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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 QMLCOMPOSITETYPEMANAGER_P_H
+#define QMLCOMPOSITETYPEMANAGER_P_H
+
+#include <qglobal.h>
+#include <private/qmlxmlparser_p.h>
+#include <private/qmlrefcount_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlXmlParser;
+class QmlEngine;
+class QmlCompiledComponent;
+class QmlComponentPrivate;
+class QmlComponent;
+class QmlCompositeTypeManager : public QObject
+{
+ Q_OBJECT
+public:
+ QmlCompositeTypeManager(QmlEngine *);
+
+ struct TypeData : public QmlRefCount
+ {
+ TypeData();
+ virtual ~TypeData();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+ QString errorDescription;
+
+ QString url;
+ QList<TypeData *> dependants;
+
+ // Return a QmlComponent if the TypeData is not in the Waiting state.
+ // The QmlComponent is owned by the TypeData, so a reference should be
+ // kept to keep the QmlComponent alive.
+ QmlComponent *toComponent(QmlEngine *);
+ // Return a QmlCompiledComponent if possible, or 0 if an error
+ // occurs
+ QmlCompiledComponent *toCompiledComponent(QmlEngine *);
+
+ struct TypeReference
+ {
+ TypeReference();
+
+ QmlType *type;
+ TypeData *unit;
+ QmlCustomParser *parser;
+ };
+
+ QList<TypeReference> types;
+
+ // Add or remove p as a waiter. When the TypeData becomes ready, the
+ // QmlComponentPrivate::typeDataReady() method will be invoked on p.
+ // The waiter is automatically removed when the typeDataReady() method
+ // is invoked, so there is no need to call remWaiter() in this case.
+ void addWaiter(QmlComponentPrivate *p);
+ void remWaiter(QmlComponentPrivate *p);
+
+ private:
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+
+ QmlXmlParser data;
+ QList<QmlComponentPrivate *> waiters;
+ QmlComponent *component;
+ QmlCompiledComponent *compiledComponent;
+ };
+
+ // Return a TypeData for url. The TypeData may be cached.
+ TypeData *get(const QUrl &url);
+ // Return a TypeData for data, with the provided base url. The TypeData
+ // will not be cached.
+ TypeData *getImmediate(const QByteArray &data, const QUrl &url);
+
+ // Clear cached types. Only types that aren't in the Waiting state will
+ // be cleared.
+ void clearCache();
+
+private Q_SLOTS:
+ void replyFinished();
+
+private:
+ void loadSource(TypeData *);
+ void compile(TypeData *);
+ void setData(TypeData *, const QByteArray &, const QUrl &);
+
+ void doComplete(TypeData *);
+ void checkComplete(TypeData *);
+
+ QmlEngine *engine;
+ typedef QHash<QString, TypeData *> Components;
+ Components components;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPOSITETYPEMANAGER_P_H
+
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
new file mode 100644
index 0000000..104f460
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** 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 <qmlcontext.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcompiledcomponent_p.h>
+#include <qmlengine.h>
+#include <qscriptengine.h>
+
+#include <qdebug.h>
+
+// 6-bits
+#define MAXIMUM_DEFAULT_OBJECTS 63
+
+QT_BEGIN_NAMESPACE
+
+QmlContextPrivate::QmlContextPrivate()
+ : parent(0), engine(0), highPriorityCount(0), component(0)
+{
+}
+
+void QmlContextPrivate::dump()
+{
+ dump(0);
+}
+
+void QmlContextPrivate::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ qWarning() << ba << properties.keys();
+ qWarning() << ba << variantProperties.keys();
+ if(parent)
+ parent->d_func()->dump(depth + 1);
+}
+
+void QmlContextPrivate::destroyed(QObject *obj)
+{
+ defaultObjects.removeAll(obj);
+ for(QHash<QString, QObject *>::Iterator iter = properties.begin();
+ iter != properties.end(); ) {
+ if(*iter == obj)
+ iter = properties.erase(iter);
+ else
+ ++iter;
+ }
+}
+
+void QmlContextPrivate::init()
+{
+ Q_Q(QmlContext);
+ //set scope chain
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue scopeObj =
+ scriptEngine->newObject(engine->d_func()->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
+ if (!parent)
+ scopeChain.append(scriptEngine->globalObject());
+ else
+ scopeChain = parent->d_func()->scopeChain;
+ scopeChain.prepend(scopeObj);
+}
+
+void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
+{
+ if(defaultObjects.count() >= (MAXIMUM_DEFAULT_OBJECTS - 1)) {
+ qWarning("QmlContext: Cannot have more than %d default objects on "
+ "one bind context.", MAXIMUM_DEFAULT_OBJECTS - 1);
+ return;
+ }
+
+ if(priority == HighPriority) {
+ defaultObjects.insert(highPriorityCount++, object);
+ } else {
+ defaultObjects.append(object);
+ }
+ QObject::connect(object, SIGNAL(destroyed(QObject*)),
+ q_ptr, SLOT(objectDestroyed(QObject*)));
+}
+
+
+/*!
+ \class QmlContext
+ \brief The QmlContext class defines a context within a QML engine.
+ \mainclass
+
+ Contexts allow data to be exposed to the QML components instantiated by the
+ QML engine.
+
+ Each QmlContext contains a set of properties, distinct from
+ its QObject properties, that allow data to be
+ explicitly bound to a context by name. The context properties are defined or
+ updated by calling QmlContext::setContextProperty(). The following example shows
+ a Qt model being bound to a context and then accessed from a QML file.
+
+ \code
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("myModel", modelData);
+
+ QmlComponent component("<ListView model=\"{myModel}\" />");
+ component.create(&context);
+ \endcode
+
+ To simplify binding and maintaining larger data sets, QObject's can be
+ added to a QmlContext. These objects are known as the context's default
+ objects. In this case all the properties of the QObject are
+ made available by name in the context, as though they were all individually
+ added by calling QmlContext::setContextProperty(). Changes to the property's
+ values are detected through the property's notify signal. This method is
+ also slightly more faster than manually adding property values.
+
+ The following example has the same effect as the one above, but it is
+ achieved using a default object.
+
+ \code
+ class MyDataSet : ... {
+ ...
+ Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged);
+ ...
+ };
+
+ MyDataSet myDataSet;
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&myDataSet);
+
+ QmlComponent component("<ListView model=\"{myModel}\" />");
+ component.create(&context);
+ \endcode
+
+ Each context may have up to 32 default objects, and objects added first take
+ precedence over those added later. All properties added explicitly by
+ QmlContext::setContextProperty() take precedence over default object properties.
+
+ Contexts are hierarchal, with the \l {QmlEngine::rootContext()}{root context}
+ being created by the QmlEngine. A component instantiated in a given context
+ has access to that context's data, as well as the data defined by its
+ ancestor contexts. Data values (including those added implicitly by the
+ default objects) in a context override those in ancestor contexts. Data
+ that should be available to all components instantiated by the QmlEngine
+ should be added to the \l {QmlEngine::rootContext()}{root context}.
+
+ In the following example,
+
+ \code
+ QmlEngine engine;
+ QmlContext context1(engine.rootContext());
+ QmlContext context2(&context1);
+ QmlContext context3(&context2);
+
+ context1.setContextProperty("a", 12);
+ context2.setContextProperty("b", 13);
+ context3.setContextProperty("a", 14);
+ context3.setContextProperty("c", 14);
+ \endcode
+
+ a QML component instantiated in context1 would have access to the "a" data,
+ a QML component instantiated in context2 would have access to the "a" and
+ "b" data, and a QML component instantiated in context3 would have access to
+ the "a", "b" and "c" data - although its "a" data would return 14, unlike
+ that in context1 or context2.
+*/
+
+/*! \internal */
+QmlContext::QmlContext(QmlEngine *e)
+: QObject(*(new QmlContextPrivate))
+{
+ Q_D(QmlContext);
+ d->engine = e;
+ d->init();
+}
+
+/*!
+ Create a new QmlContext with the given \a parentContext, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ Destroys the QmlContext.
+
+ Any expressions, or sub-contexts dependent on this context will be
+ invalidated, but not destroyed (unless they are parented to the QmlContext
+ object).
+ */
+QmlContext::~QmlContext()
+{
+ Q_D(QmlContext);
+ if(d->component) d->component->release();
+}
+
+
+/*!
+ Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
+ QmlEngine was destroyed.
+*/
+QmlEngine *QmlContext::engine() const
+{
+ Q_D(const QmlContext);
+ return d->engine;
+}
+
+/*!
+ Return the context's parent QmlContext, or 0 if this context has no
+ parent or if the parent has been destroyed.
+*/
+QmlContext *QmlContext::parentContext() const
+{
+ Q_D(const QmlContext);
+ return d->parent;
+}
+
+/*!
+ Add a default \a object to this context. The object will be added after
+ any existing default objects.
+*/
+void QmlContext::addDefaultObject(QObject *defaultObject)
+{
+ Q_D(QmlContext);
+ d->addDefaultObject(defaultObject, QmlContextPrivate::NormalPriority);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+*/
+void QmlContext::setContextProperty(const QString &name, const QVariant &value)
+{
+ Q_D(QmlContext);
+ d->variantProperties.insert(name, value);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+
+ QmlContext does \b not take ownership of \a value.
+*/
+void QmlContext::setContextProperty(const QString &name, QObject *value)
+{
+ Q_D(QmlContext);
+ d->properties.insert(name, value);
+ QObject::connect(value, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+}
+
+/*!
+ Activate this bind context.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::activate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ ep->activeContexts.push(this);
+ ep->setCurrentBindContext(this);
+ ep->contextActivated(this);
+}
+
+/*!
+ Deactivate this bind context. The previously active bind context will
+ become active, or, if there was no previously active bind context, no
+ context will be active.
+
+ \sa QmlEngine::activeContext() QmlContext::activeContext()
+*/
+void QmlContext::deactivate()
+{
+ QmlEnginePrivate *ep = engine()->d_func();
+ Q_ASSERT(ep->activeContexts.top() == this);
+ ep->activeContexts.pop();
+ if(ep->activeContexts.isEmpty())
+ ep->setCurrentBindContext(0);
+ else
+ ep->setCurrentBindContext(ep->activeContexts.top());
+ ep->contextDeactivated(this);
+}
+
+/*!
+ Returns the currently active context, or 0 if no context is active.
+
+ This method is thread-safe. The active context is maintained individually
+ for each thread. This method is equivalent to
+ \code
+ QmlEngine::activeEngine()->activeContext()
+ \endcode
+*/
+QmlContext *QmlContext::activeContext()
+{
+ QmlEngine *engine = QmlEngine::activeEngine();
+ if(engine)
+ return engine->activeContext();
+ else
+ return 0;
+}
+
+/*!
+ Resolves the URL \a src relative to the URL of the
+ containing component.
+
+ If \a src is absolute, it is simply returned.
+
+ If there is no containing component, an empty URL is returned.
+
+ \sa componentUrl
+*/
+QUrl QmlContext::resolvedUrl(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if(src.isRelative()) {
+ if(ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->component)
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if(ctxt)
+ return ctxt->d_func()->component->url.resolved(src);
+ }
+ return QUrl();
+ } else {
+ return src;
+ }
+}
+
+/*!
+ Resolves the component URI \a src relative to the URL of the
+ containing component, and according to the
+ \link QmlEngine::nameSpacePaths() namespace paths\endlink of the
+ context's engine, returning the resolved URL.
+
+ \sa componentUrl
+*/
+QUrl QmlContext::resolvedUri(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if(src.isRelative()) {
+ if(ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->component)
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if(ctxt)
+ return ctxt->d_func()->engine->componentUrl(src, ctxt->d_func()->component->url);
+ }
+ return QUrl();
+ } else {
+ return ctxt->d_func()->engine->componentUrl(src, QUrl());
+ }
+}
+
+void QmlContext::objectDestroyed(QObject *object)
+{
+ Q_D(QmlContext);
+ d->destroyed(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
new file mode 100644
index 0000000..9e3b6d8
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 QMLCONTEXT_H
+#define QMLCONTEXT_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlEngine;
+class QmlRefCount;
+class QmlContextPrivate;
+class Q_DECLARATIVE_EXPORT QmlContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlContext)
+
+public:
+ QmlContext(QmlContext *parent, QObject *objParent=0);
+ virtual ~QmlContext();
+
+ QmlEngine *engine() const;
+ QmlContext *parentContext() const;
+
+ void addDefaultObject(QObject *);
+ void setContextProperty(const QString &, QObject *);
+ void setContextProperty(const QString &, const QVariant &);
+
+ void activate();
+ void deactivate();
+
+ static QmlContext *activeContext();
+
+ QUrl resolvedUri(const QUrl &);
+ QUrl resolvedUrl(const QUrl &);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *);
+
+private:
+ friend class QmlEngine;
+ friend class QmlEnginePrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlContextScriptClass;
+ friend class QmlObjectScriptClass;
+ friend class QmlComponent;
+ friend class QmlScriptPrivate;
+ friend class QmlBoundSignalProxy;
+ QmlContext(QmlEngine *);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCONTEXT_H
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
new file mode 100644
index 0000000..8c51a6b
--- /dev/null
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 QMLCONTEXT_P_H
+#define QMLCONTEXT_P_H
+
+#include <qmlcontext.h>
+#include <private/qobject_p.h>
+#include <qhash.h>
+#include <qscriptvalue.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlEngine;
+class QmlCompiledComponent;
+
+class QmlContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlContext)
+public:
+ QmlContextPrivate();
+
+ QmlContext *parent;
+ QmlEngine *engine;
+ QHash<QString, QObject *> properties;
+ QHash<QString, QVariant> variantProperties;
+
+ QObjectList defaultObjects;
+ int highPriorityCount;
+
+ QScriptValueList scopeChain;
+
+ QmlCompiledComponent *component;
+ void init();
+
+ void dump();
+ void dump(int depth);
+
+ void destroyed(QObject *);
+
+ enum Priority {
+ HighPriority,
+ NormalPriority
+ };
+ void addDefaultObject(QObject *, Priority);
+};
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXT_P_H
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
new file mode 100644
index 0000000..a342ca8
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 "qmlcustomparser.h"
+
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlCustomParser
+ \brief The QmlCustomParser class allows you to add new arbitrary types to QML.
+
+ By subclassing QmlCustomParser, you can add an XML parser for building a
+ particular type.
+
+ The subclass must implement compile() and create(), and define itself in
+ the meta type system with one of the macros:
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER(Name, parserClass)
+ \endcode
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER_NS("XmlNamespaceUri", Name, parserClass)
+ \endcode
+*/
+
+/*!
+ \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader, bool *ok)
+
+ Upon entry to this function, \a reader is positioned on a QXmlStreamReader::StartElement
+ with the name specified when the class was defined with the QML_DEFINE_CUSTOM_PARSER macro.
+
+ The custom parser must consume tokens from \a reader until the EndElement matching the
+ initial start element is reached, or until error.
+
+ On return, \c *ok indicates success.
+
+ The returned QByteArray contains data meaningful only to the custom parser; the
+ type engine will pass this same data to create() when making an instance of the data.
+
+ The QByteArray may be cached between executions of the system, so it must contain
+ correctly-serialized data (not, for example, pointers to stack objects).
+*/
+
+/*!
+ \fn QVariant QmlCustomParser::create(const QByteArray &data)
+
+ This function returns a QVariant containing the value represented by \a data, which
+ is a block of data previously returned by a call to compile().
+
+ If the compile is for a type, the variant should be a pointer to the
+ correctly-named QObject subclass (i.e. the one defined by QML_DEFINE_TYPE for
+ the same-named type as this custom parser is defined for).
+*/
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcustomparser.h b/src/declarative/qml/qmlcustomparser.h
new file mode 100644
index 0000000..9de1be4
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCUSTOMPARSER_H
+#define QMLCUSTOMPARSER_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qxmlstream.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlCustomParser
+{
+public:
+ virtual ~QmlCustomParser() {}
+
+ virtual QByteArray compile(QXmlStreamReader&, bool *ok)=0;
+ virtual QVariant create(const QByteArray &)=0;
+
+ struct Register {
+ Register(const char *name, QmlCustomParser *parser) {
+ qmlRegisterCustomParser(name, parser);
+ }
+ };
+ template<typename T>
+ struct Define {
+ static Register instance;
+ };
+};
+#define QML_DEFINE_CUSTOM_PARSER(name, parserClass) \
+ template<> QmlCustomParser::Register QmlCustomParser::Define<parserClass>::instance(# name, new parserClass);
+#define QML_DEFINE_CUSTOM_PARSER_NS(namespacestring, name, parserClass) \
+ template<> QmlCustomParser::Register QmlCustomParser::Define<parserClass>::instance(namespacestring "/" # name, new parserClass);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
new file mode 100644
index 0000000..274b542
--- /dev/null
+++ b/src/declarative/qml/qmldom.cpp
@@ -0,0 +1,1372 @@
+/****************************************************************************
+**
+** 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 "qmldom.h"
+#include "qmldom_p.h"
+#include "private/qmlxmlparser_p.h"
+#include "private/qmlcompiler_p.h"
+#include "qmlcompiledcomponent_p.h"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate()
+: root(0)
+{
+}
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate(const QmlDomDocumentPrivate &other)
+: QSharedData(other), root(0)
+{
+ root = other.root;
+ if(root) root->addref();
+}
+
+QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
+{
+ if(root) root->release();
+}
+
+/*!
+ \class QmlDomDocument
+ \brief The QmlDomDocument class represents the root of a QML document
+
+ A QML document is a self-contained snippet of QML, usually contained in a
+ single file. Each document has a version number, accessible through
+ QmlDomDocument::version(), and a root object, accessible through
+ QmlDomDocument::rootObject().
+
+ The QmlDomDocument class allows the programmer to load a QML document, by
+ calling QmlDomDocument::load(), manipulate it and save it to textual form
+ by calling QmlDomDocument::save(). By using the QML DOM API, editors can
+ non-destructively modify a QML document even if they only understand a
+ subset of the total QML functionality.
+
+ The following example loads a QML file from disk, and prints out its root
+ object type and the properties assigned in the root object.
+ \code
+ QFile file(inputFileName);
+ file.open(QIODevice::ReadOnly);
+ QByteArray xmlData = file.readAll();
+
+ QDomDocument document;
+ document.load(xmlData);
+
+ QDomObject rootObject = document.rootObject();
+ qDebug() << rootObject.objectType();
+ foreach(QmlDomProperty property, rootObject.properties())
+ qDebug() << property.propertyName();
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument()
+: d(new QmlDomDocumentPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument(const QmlDomDocument &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDocument
+*/
+QmlDomDocument::~QmlDomDocument()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDocument.
+*/
+QmlDomDocument &QmlDomDocument::operator=(const QmlDomDocument &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the version number of the Qml document. Currently only version
+ 1 exists.
+*/
+int QmlDomDocument::version() const
+{
+ return 1;
+}
+
+/*!
+ Loads a QmlDomDocument from \a data. \a data should be valid QML XML
+ data. On success, true is returned. If the \a data is malformed, false
+ is returned and QmlDomDocument::loadError() contains an error description.
+
+ \sa QmlDomDocument::save() QmlDomDocument::loadError()
+*/
+bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data)
+{
+ d->error = QString();
+
+ QmlXmlParser parser;
+ if(!parser.parse(data)) {
+ d->error = parser.errorDescription();
+ return false;
+ }
+
+ QmlCompiledComponent component;
+ QmlCompiler compiler;
+ // ###
+// compiler.compile(engine, parser, &component);
+
+ if(compiler.isError()) {
+ d->error = compiler.errorDescription();
+ return false;
+ }
+
+ if(parser.tree()) {
+ component.dump(0, parser.tree());
+ d->root = parser.tree();
+ d->root->addref();
+ }
+
+ return true;
+}
+
+/*!
+ Returns the last load error. The load error will be reset after a
+ successful call to load().
+
+ \sa load()
+*/
+QString QmlDomDocument::loadError() const
+{
+ return d->error;
+}
+
+/*!
+ Return a saved copy of the QmlDomDocument. The returned data will be valid
+ QML XML data.
+
+ \sa load()
+*/
+QByteArray QmlDomDocument::save() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns the document's root object, or an invalid QmlDomObject if the
+ document has no root.
+
+ In the sample QML below, the root object will be the QFxItem type.
+ \code
+ <Item>
+ <Text text="Hello World" />
+ </Item>
+ \endcode
+*/
+QmlDomObject QmlDomDocument::rootObject() const
+{
+ QmlDomObject rv;
+ rv.d->object = d->root;
+ if(rv.d->object) rv.d->object->addref();
+ return rv;
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate()
+: property(0)
+{
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate(const QmlDomPropertyPrivate &other)
+: QSharedData(other), property(0)
+{
+ property = other.property;
+ if(property) property->addref();
+}
+
+QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
+{
+ if(property) property->release();
+}
+
+/*!
+ \class QmlDomProperty
+ \brief The QmlDomProperty class represents one property assignment in the
+ QML DOM tree
+
+ Properties in QML can be assigned QML \l {QmlDomValue}{values}.
+
+ \sa QmlDomObject
+*/
+
+/*!
+ Construct an invalid QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty()
+: d(new QmlDomPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty(const QmlDomProperty &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomProperty.
+*/
+QmlDomProperty::~QmlDomProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomProperty.
+*/
+QmlDomProperty &QmlDomProperty::operator=(const QmlDomProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the name of this property.
+
+ \code
+ <Text x="10" y="10" font.bold="true" />
+ \endcode
+
+ As illustrated above, a property name can be a simple string, such as "x" or
+ "y", or a more complex "dot property", such as "font.bold". In both cases
+ the full name is returned ("x", "y" and "font.bold") by this method.
+
+ For dot properties, a split version of the name can be accessed by calling
+ QmlDomProperty::propertyNameParts().
+
+ \sa QmlDomProperty::propertyNameParts()
+*/
+QByteArray QmlDomProperty::propertyName() const
+{
+ return d->propertyName;
+}
+
+/*!
+ Return the name of this property, split into multiple parts in the case
+ of dot properties.
+
+ \code
+ <Text x="10" y="10" font.bold="true" />
+ \endcode
+
+ For each of the properties shown above, this method would return ("x"),
+ ("y") and ("font", "bold").
+
+ \sa QmlDomProperty::propertyName()
+*/
+QList<QByteArray> QmlDomProperty::propertyNameParts() const
+{
+ if(d->propertyName.isEmpty()) return QList<QByteArray>();
+ else return d->propertyName.split('.');
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \code
+ <Text text="hello" />
+ <Text>hello</Text>
+ \endcode
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomProperty::isDefaultProperty() const
+{
+ return d->property && d->property->isDefault;
+}
+
+/*!
+ Returns the QmlDomValue that is assigned to this property, or an invalid
+ QmlDomValue if no value is assigned.
+*/
+QmlDomValue QmlDomProperty::value() const
+{
+ QmlDomValue rv;
+ if(d->property) {
+ rv.d->property = d->property;
+ rv.d->value = d->property->values.at(0);
+ rv.d->property->addref();
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Sets the QmlDomValue that is assigned to this property to \a value.
+*/
+void QmlDomProperty::setValue(const QmlDomValue &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomProperty::setValue(const QmlDomValue &): Not Implemented");
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate()
+: object(0), isVirtualComponent(false)
+{
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate(const QmlDomObjectPrivate &other)
+: QSharedData(other), object(0), isVirtualComponent(false)
+{
+ object = other.object;
+ if(object) object->addref();
+ isVirtualComponent = other.isVirtualComponent;
+}
+
+QmlDomObjectPrivate::~QmlDomObjectPrivate()
+{
+ if(object) object->release();
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties() const
+{
+ Properties rv;
+
+ for(QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ object->properties.begin();
+ iter != object->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+ return rv;
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties(QmlParser::Property *property) const
+{
+ Properties rv;
+
+ if(property->value) {
+
+ for(QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ property->value->properties.begin();
+ iter != property->value->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+
+ QByteArray name(property->name + ".");
+ for(Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter)
+ iter->second.prepend(name);
+
+ } else {
+
+ // We don't display "id" sets as a property in the dom
+ if(property->values.count() != 1 ||
+ property->values.at(0)->type != QmlParser::Value::Id)
+ rv << qMakePair(property, property->name);
+
+ }
+
+ return rv;
+}
+
+/*!
+ \class QmlDomObject
+ \brief The QmlDomObject class represents an object instantiation.
+
+ Each object instantiated in a QML file has a corresponding QmlDomObject
+ node in the QML DOM.
+
+ In addition to the type information that determines the object to
+ instantiate, QmlDomObject's also have a set of associated QmlDomProperty's.
+ Each QmlDomProperty represents a QML property assignment on the instantiated
+ object. For example,
+
+ \code
+ <QGraphicsWidget opacity="0.5" size="100x100" />
+ \endcode
+
+ describes a single QmlDomObject - "QGraphicsWidget" - with two properties,
+ "opacity" and "size". Obviously QGraphicsWidget has many more properties than just
+ these two, but the QML DOM representation only contains those assigned
+ values (or bindings) in the QML file.
+
+ The DOM tree can be modified to include new property assignments by calling
+ QmlDomObject::addProperty(). Existing property assignments can be modified
+ through the QmlDomProperty::setValue() method, or removed entirely by
+ calling QmlDomObject::removeProperty().
+*/
+
+/*!
+ Construct an invalid QmlDomObject.
+*/
+QmlDomObject::QmlDomObject()
+: d(new QmlDomObjectPrivate)
+{
+}
+
+/*!
+ Construct a new QmlDomObject with the specified \a objectType.
+*/
+QmlDomObject::QmlDomObject(const QByteArray &objectType)
+: d(new QmlDomObjectPrivate)
+{
+ Q_UNUSED(objectType);
+ qWarning("QmlDomObject::QmlDomObject(const QByteArray &): Not implemented");
+}
+
+/*!
+ Create a copy of \a other QmlDomObject.
+*/
+QmlDomObject::QmlDomObject(const QmlDomObject &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomObject.
+*/
+QmlDomObject::~QmlDomObject()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomObject.
+*/
+QmlDomObject &QmlDomObject::operator=(const QmlDomObject &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomObject, false otherwise.
+*/
+bool QmlDomObject::isValid() const
+{
+ return d->object != 0;
+}
+
+/*!
+ Returns the type name of this object.
+
+ For example, the type of this object would be "QGraphicsWidget".
+ \code
+ <QGraphicsWidget />
+ \endcode
+*/
+QByteArray QmlDomObject::objectType() const
+{
+ if(d->object) return d->object->typeName;
+ else return QByteArray();
+}
+
+/*!
+ Returns the QML id assigned to this object, or an empty QByteArray if no id
+ has been assigned.
+
+ For example, the object id of this object would be "MyText".
+ \code
+ <Text id="MyText" />
+ \endcode
+*/
+QByteArray QmlDomObject::objectId() const
+{
+ if(d->object) return d->object->id;
+ else return QByteArray();
+}
+
+/*!
+ Set the object \a id. If any other object within the DOM tree has the same
+ id, the other object's id will be cleared.
+*/
+void QmlDomObject::setObjectId(const QByteArray &id)
+{
+ Q_UNUSED(id);
+ qWarning("QmlDomObject::setObjectId(const QByteArray &): Not implemented");
+}
+
+
+/*!
+ Returns the list of assigned properties on this object.
+
+ In the following example, "text" and "x" properties would be returned.
+ \code
+ <Text text="Hello world!" x="100" />
+ \endcode
+*/
+QList<QmlDomProperty> QmlDomObject::properties() const
+{
+ QList<QmlDomProperty> rv;
+
+ if(!d->object)
+ return rv;
+
+ QmlDomObjectPrivate::Properties properties = d->properties();
+ for(int ii = 0; ii < properties.count(); ++ii) {
+
+ QmlDomProperty domProperty;
+ domProperty.d->property = properties.at(ii).first;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = properties.at(ii).second;
+ rv << domProperty;
+
+ }
+
+ if(d->object->defaultProperty) {
+ QmlDomProperty domProperty;
+ domProperty.d->property = d->object->defaultProperty;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = d->object->defaultProperty->name;
+ rv << domProperty;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the object's \a name property if a value has been assigned to
+ it, or an invalid QmlDomProperty otherwise.
+
+ In the example below, \c {object.property("src")} would return a valid
+ QmlDomProperty, and \c {object.property("tile")} an invalid QmlDomProperty.
+
+ \code
+ <Image src="sample.jpg" />
+ \endcode
+*/
+QmlDomProperty QmlDomObject::property(const QByteArray &name) const
+{
+ QList<QmlDomProperty> props = properties();
+ for(int ii = 0; ii < props.count(); ++ii)
+ if(props.at(ii).propertyName() == name)
+ return props.at(ii);
+ return QmlDomProperty();
+}
+
+/*!
+ Remove the property \a name from this object, if it exists. Otherwise does
+ nothing.
+*/
+void QmlDomObject::removeProperty(const QByteArray &name)
+{
+ Q_UNUSED(name);
+ qWarning("QmlDomObject::removeProperty(const QByteArray &): Not implemented");
+}
+
+/*!
+ Adds the property \a name with the specified \a value to this object. If
+ a property by \a name already exists, it will be removed.
+*/
+void QmlDomObject::addProperty(const QByteArray &name, const QmlDomValue &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+ qWarning("QmlDomObject::addProperty(const QByteArray &, const QmlDomValue &): Not implemented");
+}
+
+/*!
+ Returns true if this object is a custom type. Custom types are special
+ types that allow embeddeding non-QML data, such as SVG or HTML data,
+ directly into QML files.
+
+ \note Currently this method will always return false, and is a placekeeper
+ for future functionality.
+
+ \sa QmlDomObject::customTypeData()
+*/
+bool QmlDomObject::isCustomType() const
+{
+ return false;
+}
+
+/*!
+ Sets the custom type \a data. If this type is not a custom type, this
+ method does nothing.
+
+ \sa QmlDomObject::isCustomType() QmlDomObject::customTypeData()
+*/
+void QmlDomObject::setCustomTypeData(const QByteArray &data)
+{
+ Q_UNUSED(data);
+ qWarning("QmlDomObject::setCustomTypeData(const QByteArray &): Not implemented");
+}
+
+/*!
+ If this object represents a custom type, returns the data associated with
+ the custom type, otherwise returns an empty QByteArray().
+ QmlDomObject::isCustomType() can be used to check if this object represents
+ a custom type.
+*/
+QByteArray QmlDomObject::customTypeData() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns true if this object is a sub-component object. Sub-component
+ objects can be converted into QmlDomComponent instances by calling
+ QmlDomObject::toComponent().
+
+ \sa QmlDomObject::toComponent()
+*/
+bool QmlDomObject::isComponent() const
+{
+ return d->isVirtualComponent ||
+ (d->object && d->object->typeName == "Component");
+}
+
+/*!
+ Returns a QmlDomComponent for this object if it is a sub-component, or
+ an invalid QmlDomComponent if not. QmlDomObject::isComponent() can be used
+ to check if this object represents a sub-component.
+
+ \sa QmlDomObject::isComponent()
+*/
+QmlDomComponent QmlDomObject::toComponent() const
+{
+ QmlDomComponent rv;
+ if(isComponent())
+ rv.d = d;
+ return rv;
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
+: value(0)
+{
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &other)
+: QSharedData(other), value(0)
+{
+ value = other.value;
+ if(value) value->addref();
+}
+
+QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
+{
+ if(value) value->release();
+}
+
+/*!
+ \class QmlDomValueLiteral
+ \brief The QmlDomValueLiteral class represents a literal value.
+
+ A literal value is a simple value, written inline with the QML. In the
+ example below, the "x", "y" and "color" properties are being assigned
+ literal values.
+
+ \code
+ <Rect x="10" y="10" color="red" />
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral(const QmlDomValueLiteral &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::~QmlDomValueLiteral()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueLiteral.
+*/
+QmlDomValueLiteral &QmlDomValueLiteral::operator=(const QmlDomValueLiteral &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the literal value.
+
+ In the example below, the literal value will be the string "10".
+ \code
+ <Rect x="10" />
+ \endcode
+*/
+QString QmlDomValueLiteral::literal() const
+{
+ if(d->value) return d->value->primitive;
+ else return QString();
+}
+
+/*!
+ Sets the literal \a value.
+*/
+void QmlDomValueLiteral::setLiteral(const QString &value)
+{
+ Q_UNUSED(value);
+ qWarning("QmlDomValueLiteral::setLiteral(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueBinding
+ \brief The QmlDomValueBinding class represents a property binding.
+
+ A property binding is an ECMAScript expression assigned to a property. In
+ the example below, the "x" property is being assigned a property binding.
+
+ \code
+ <Rect x="{Other.x}" />
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding(const QmlDomValueBinding &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueBinding.
+*/
+QmlDomValueBinding::~QmlDomValueBinding()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueBinding.
+*/
+QmlDomValueBinding &QmlDomValueBinding::operator=(const QmlDomValueBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the binding expression.
+
+ In the example below, the string "Other.x" will be returned.
+ \code
+ <Rect x="{Other.x}" />
+ \endcode
+*/
+QString QmlDomValueBinding::binding() const
+{
+ if(d->value)
+ return d->value->primitive.mid(1, d->value->primitive.length() - 2);
+ else
+ return QString();
+}
+
+/*!
+ Sets the binding \a expression.
+*/
+void QmlDomValueBinding::setBinding(const QString &expression)
+{
+ Q_UNUSED(expression);
+ qWarning("QmlDomValueBinding::setBinding(const QString &): Not implemented");
+}
+
+/*!
+ \class QmlDomValueValueSource
+ \brief The QmlDomValueValueSource class represents a value source assignment value.
+
+ In QML, value sources are special value generating types that may be
+ assigned to properties. Value sources inherit the QmlPropertyValueSource
+ class. In the example below, the "x" property is being assigned the
+ NumericAnimation value source.
+
+ \code
+ <Rect>
+ <x>
+ <NumericAnimation from="0" to="100" repeat="true" running="true" />
+ </x>
+ </Rect>
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource(const QmlDomValueValueSource &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::~QmlDomValueValueSource()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueSource.
+*/
+QmlDomValueValueSource &QmlDomValueValueSource::operator=(const QmlDomValueValueSource &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value source object.
+
+ In the example below, an object representing the NumericAnimation will be
+ returned.
+ \code
+ <Rect>
+ <x>
+ <NumericAnimation from="0" to="100" repeat="true" running="true" />
+ </x>
+ </Rect>
+ \endcode
+*/
+QmlDomObject QmlDomValueValueSource::object() const
+{
+ QmlDomObject rv;
+ if(d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return QmlDomObject();
+}
+
+/*!
+ Sets the value source \a object.
+*/
+void QmlDomValueValueSource::setObject(const QmlDomObject &object)
+{
+ Q_UNUSED(object);
+ qWarning("QmlDomValueValueSource::setObject(const QmlDomObject &): Not implemented");
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate()
+: property(0), value(0)
+{
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate(const QmlDomValuePrivate &other)
+: QSharedData(other), property(0), value(0)
+{
+ property = other.property;
+ value = other.value;
+ if(property) property->addref();
+ if(value) value->addref();
+}
+
+QmlDomValuePrivate::~QmlDomValuePrivate()
+{
+ if(property) property->release();
+ if(value) value->release();
+}
+
+/*!
+ \class QmlDomValue
+ \brief The QmlDomValue class represents a generic Qml value.
+
+ QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
+ QML, properties can be assigned various different values, including basic
+ literals, property bindings, property value sources, objects and lists of
+ values. The QmlDomValue class allows a programmer to determine the specific
+ value type being assigned and access more detailed information through a
+ corresponding value type class.
+
+ For example, in the following example,
+
+ \code
+ <Text text="Hello World!" y="{Other.y}" />
+ \endcode
+
+ The text property is being assigned a literal, and the y property a property
+ binding. To output the values assigned to the text and y properties in the
+ above example from C++,
+
+ \code
+ QmlDomDocument document;
+ QmlDomObject root = document.rootObject();
+
+ QmlDomProperty text = root.property("text");
+ if(text.value().isLiteral()) {
+ QmlDomValueLiteral literal = text.value().toLiteral();
+ qDebug() << literal.literal();
+ }
+
+ QmlDomProperty y = root.property("y");
+ if(y.value().isBinding()) {
+ QmlDomValueBinding binding = y.value().toBinding();
+ qDebug() << binding.binding();
+ }
+ \endcode
+*/
+
+/*!
+ Construct an invalid QmlDomValue.
+*/
+QmlDomValue::QmlDomValue()
+: d(new QmlDomValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValue.
+*/
+QmlDomValue::QmlDomValue(const QmlDomValue &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValue
+*/
+QmlDomValue::~QmlDomValue()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValue.
+*/
+QmlDomValue &QmlDomValue::operator=(const QmlDomValue &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \enum QmlDomValue::Type
+
+ The type of the QmlDomValue node.
+
+ \value Invalid The QmlDomValue is invalid.
+ \value Literal The QmlDomValue is a literal value assignment. Use QmlDomValue::toLiteral() to access the type instance.
+ \value PropertyBinding The QmlDomValue is a property binding. Use QmlDomValue::toBinding() to access the type instance.
+ \value ValueSource The QmlDomValue is a property value source. Use QmlDomValue::toValueSource() to access the type instance.
+ \value Object The QmlDomValue is an object assignment. Use QmlDomValue::toObject() to access the type instnace.
+ \value List The QmlDomValue is a list of other values. Use QmlDomValue::toList() to access the type instance.
+*/
+
+/*!
+ Returns the type of this QmlDomValue.
+*/
+QmlDomValue::Type QmlDomValue::type() const
+{
+ if(d->property)
+ if(QmlMetaType::isList(d->property->type) ||
+ QmlMetaType::isQmlList(d->property->type) ||
+ (d->property && d->property->values.count() > 1))
+ return List;
+
+ QmlParser::Value *value = d->value;
+ if (!value && !d->property)
+ return Invalid;
+
+ switch(value->type) {
+ case QmlParser::Value::Unknown:
+ return Invalid;
+ case QmlParser::Value::Literal:
+ return Literal;
+ case QmlParser::Value::PropertyBinding:
+ return PropertyBinding;
+ case QmlParser::Value::ValueSource:
+ return ValueSource;
+ case QmlParser::Value::Component:
+ case QmlParser::Value::CreatedObject:
+ return Object;
+ case QmlParser::Value::SignalObject:
+ return Invalid;
+ case QmlParser::Value::SignalExpression:
+ return Literal;
+ case QmlParser::Value::Id:
+ return Invalid;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns true if this is an invalid value, otherwise false.
+*/
+bool QmlDomValue::isInvalid() const
+{
+ return type() == Invalid;
+}
+
+/*!
+ Returns true if this is a literal value, otherwise false.
+*/
+bool QmlDomValue::isLiteral() const
+{
+ return type() == Literal;
+}
+
+/*!
+ Returns true if this is a property binding value, otherwise false.
+*/
+bool QmlDomValue::isBinding() const
+{
+ return type() == PropertyBinding;
+}
+
+/*!
+ Returns true if this is a value source value, otherwise false.
+*/
+bool QmlDomValue::isValueSource() const
+{
+ return type() == ValueSource;
+}
+
+/*!
+ Returns true if this is an object value, otherwise false.
+*/
+bool QmlDomValue::isObject() const
+{
+ return type() == Object;
+}
+
+/*!
+ Returns true if this is a list value, otherwise false.
+*/
+bool QmlDomValue::isList() const
+{
+ return type() == List;
+}
+
+/*!
+ Returns a QmlDomValueLiteral if this value is a literal type, otherwise
+ returns an invalid QmlDomValueLiteral.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueLiteral QmlDomValue::toLiteral() const
+{
+ QmlDomValueLiteral rv;
+ if(type() == Literal) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueBinding if this value is a property binding type,
+ otherwise returns an invalid QmlDomValueBinding.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueBinding QmlDomValue::toBinding() const
+{
+ QmlDomValueBinding rv;
+ if(type() == PropertyBinding) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueSource if this value is a property value source
+ type, otherwise returns an invalid QmlDomValueValueSource.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueSource QmlDomValue::toValueSource() const
+{
+ QmlDomValueValueSource rv;
+ if(type() == ValueSource) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomObject if this value is an object assignment type, otherwise
+ returns an invalid QmlDomObject.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomObject QmlDomValue::toObject() const
+{
+ QmlDomObject rv;
+ if(type() == Object) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomList if this value is a list type, otherwise returns an
+ invalid QmlDomList.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomList QmlDomValue::toList() const
+{
+ QmlDomList rv;
+ if(type() == List) {
+ rv.d = d;
+ }
+ return rv;
+}
+
+/*!
+ \class QmlDomList
+ \brief The QmlDomList class represents a list of values assigned to a QML property.
+
+ Lists of values can be assigned to properties. For example, the following
+ example assigns multiple objects to Item's "children" property
+ \code
+ <Item>
+ <children>
+ <Text />
+ <Rect />
+ </children>
+ </Item>
+ \endcode
+
+ Lists can also be implicitly created by assigning multiple
+ \l {QmlDomValueValueSource}{value sources} or constants to a property.
+ \code
+ <Item x="10">
+ <x>
+ <NumericAnimation running="false" from="0" to="100" />
+ </x>
+ </Item>
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomList.
+*/
+QmlDomList::QmlDomList()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomList.
+*/
+QmlDomList::QmlDomList(const QmlDomList &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomList.
+*/
+QmlDomList::~QmlDomList()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomList.
+*/
+QmlDomList &QmlDomList::operator=(const QmlDomList &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the list of QmlDomValue's.
+*/
+QList<QmlDomValue> QmlDomList::values() const
+{
+ QList<QmlDomValue> rv;
+ if(!d->property)
+ return rv;
+
+ for(int ii = 0; ii < d->property->values.count(); ++ii) {
+ QmlDomValue v;
+ v.d->value = d->property->values.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
+ return rv;
+}
+
+/*!
+ Set the list of QmlDomValue's to \a values.
+*/
+void QmlDomList::setValues(const QList<QmlDomValue> &values)
+{
+ Q_UNUSED(values);
+ qWarning("QmlDomList::setValues(const QList<QmlDomValue> &): Not implemented");
+}
+
+
+/*!
+ \class QmlDomComponent
+ \brief The QmlDomComponent class represents sub-component within a QML document.
+
+ Sub-components are QmlComponents defined within a QML document. The
+ following example shows the definition of a sub-component with the id
+ "ListDelegate".
+
+ \code
+ <Item>
+ <Component id="ListDelegate">
+ <Text text="{modelData.text}" />
+ </Component>
+ </Item>
+ \endcode
+
+ Like QmlDomDocument's, components contain a single root object.
+*/
+
+/*!
+ Construct an empty QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent(const QmlDomComponent &other)
+: QmlDomObject(other)
+{
+}
+
+/*!
+ Destroy the QmlDomComponent.
+*/
+QmlDomComponent::~QmlDomComponent()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomComponent.
+*/
+QmlDomComponent &QmlDomComponent::operator=(const QmlDomComponent &other)
+{
+ static_cast<QmlDomObject &>(*this) = other;
+ return *this;
+}
+
+/*!
+ Returns the component's root object.
+
+ In the example below, the root object is the "Text" object.
+ \code
+ <Item>
+ <Component id="ListDelegate">
+ <Text text="{modelData.text}" />
+ </Component>
+ </Item>
+ \endcode
+*/
+QmlDomObject QmlDomComponent::componentRoot() const
+{
+ QmlDomObject rv;
+ if(d->isVirtualComponent) {
+ rv.d->object = d->object;
+ rv.d->object->addref();
+ } else if(d->object) {
+ QmlParser::Object *obj = 0;
+ if(d->object->defaultProperty &&
+ d->object->defaultProperty->values.count() == 1 &&
+ d->object->defaultProperty->values.at(0)->object)
+ obj = d->object->defaultProperty->values.at(0)->object;
+
+ if(obj) {
+ rv.d->object = obj;
+ rv.d->object->addref();
+ }
+ }
+
+ return rv;
+}
+
+/*!
+ Set the component's \a root object.
+*/
+void QmlDomComponent::setComponentRoot(const QmlDomObject &root)
+{
+ Q_UNUSED(root);
+ qWarning("QmlDomComponent::setComponentRoot(const QmlDomObject &): Not implemented");
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
new file mode 100644
index 0000000..47a89d9
--- /dev/null
+++ b/src/declarative/qml/qmldom.h
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** 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 QMLDOM_H
+#define QMLDOM_H
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QByteArray;
+class QmlDomObject;
+class QmlDomList;
+class QmlDomValue;
+class QmlEngine;
+class QmlDomComponent;
+class QIODevice;
+
+class QmlDomDocumentPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomDocument
+{
+public:
+ QmlDomDocument();
+ QmlDomDocument(const QmlDomDocument &);
+ ~QmlDomDocument();
+ QmlDomDocument &operator=(const QmlDomDocument &);
+
+ int version() const;
+
+ QString loadError() const;
+ bool load(QmlEngine *, const QByteArray &);
+ QByteArray save() const;
+
+ QmlDomObject rootObject() const;
+private:
+ QSharedDataPointer<QmlDomDocumentPrivate> d;
+};
+
+class QmlDomPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomProperty
+{
+public:
+ QmlDomProperty();
+ QmlDomProperty(const QmlDomProperty &);
+ ~QmlDomProperty();
+ QmlDomProperty &operator=(const QmlDomProperty &);
+
+ QByteArray propertyName() const;
+ QList<QByteArray> propertyNameParts() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomValue value() const;
+ void setValue(const QmlDomValue &);
+
+private:
+ friend class QmlDomObject;
+ QSharedDataPointer<QmlDomPropertyPrivate> d;
+};
+
+class QmlDomObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomObject
+{
+public:
+ QmlDomObject();
+ QmlDomObject(const QByteArray &);
+ QmlDomObject(const QmlDomObject &);
+ ~QmlDomObject();
+ QmlDomObject &operator=(const QmlDomObject &);
+
+ bool isValid() const;
+
+ QByteArray objectType() const;
+ QByteArray objectId() const;
+
+ void setObjectId(const QByteArray &);
+
+ QList<QmlDomProperty> properties() const;
+ QmlDomProperty property(const QByteArray &) const;
+
+ void removeProperty(const QByteArray &);
+ void addProperty(const QByteArray &, const QmlDomValue &);
+
+ bool isCustomType() const;
+ QByteArray customTypeData() const;
+ void setCustomTypeData(const QByteArray &);
+
+ bool isComponent() const;
+ QmlDomComponent toComponent() const;
+
+private:
+ friend class QmlDomDocument;
+ friend class QmlDomComponent;
+ friend class QmlDomValue;
+ friend class QmlDomValueValueSource;
+ QSharedDataPointer<QmlDomObjectPrivate> d;
+};
+
+class QmlDomValuePrivate;
+class QmlDomBasicValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlDomValueLiteral
+{
+public:
+ QmlDomValueLiteral();
+ QmlDomValueLiteral(const QmlDomValueLiteral &);
+ ~QmlDomValueLiteral();
+ QmlDomValueLiteral &operator=(const QmlDomValueLiteral &);
+
+ QString literal() const;
+ void setLiteral(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueBinding
+{
+public:
+ QmlDomValueBinding();
+ QmlDomValueBinding(const QmlDomValueBinding &);
+ ~QmlDomValueBinding();
+ QmlDomValueBinding &operator=(const QmlDomValueBinding &);
+
+ QString binding() const;
+ void setBinding(const QString &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueSource
+{
+public:
+ QmlDomValueValueSource();
+ QmlDomValueValueSource(const QmlDomValueValueSource &);
+ ~QmlDomValueValueSource();
+ QmlDomValueValueSource &operator=(const QmlDomValueValueSource &);
+
+ QmlDomObject object() const;
+ void setObject(const QmlDomObject &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomComponent : public QmlDomObject
+{
+public:
+ QmlDomComponent();
+ QmlDomComponent(const QmlDomComponent &);
+ ~QmlDomComponent();
+ QmlDomComponent &operator=(const QmlDomComponent &);
+
+ QmlDomObject componentRoot() const;
+ void setComponentRoot(const QmlDomObject &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValue
+{
+public:
+ enum Type {
+ Invalid,
+ Literal,
+ PropertyBinding,
+ ValueSource,
+ Object,
+ List
+ };
+
+ QmlDomValue();
+ QmlDomValue(const QmlDomValue &);
+ ~QmlDomValue();
+ QmlDomValue &operator=(const QmlDomValue &);
+
+ Type type() const;
+
+ bool isInvalid() const;
+ bool isLiteral() const;
+ bool isBinding() const;
+ bool isValueSource() const;
+ bool isObject() const;
+ bool isList() const;
+
+ QmlDomValueLiteral toLiteral() const;
+ QmlDomValueBinding toBinding() const;
+ QmlDomValueValueSource toValueSource() const;
+ QmlDomObject toObject() const;
+ QmlDomList toList() const;
+
+private:
+ friend class QmlDomProperty;
+ friend class QmlDomList;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomList
+{
+public:
+ QmlDomList();
+ QmlDomList(const QmlDomList &);
+ ~QmlDomList();
+ QmlDomList &operator=(const QmlDomList &);
+
+ QList<QmlDomValue> values() const;
+ void setValues(const QList<QmlDomValue> &);
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_H
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
new file mode 100644
index 0000000..8ea56bf
--- /dev/null
+++ b/src/declarative/qml/qmldom_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 QMLDOM_P_H
+#define QMLDOM_P_H
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+#include "qmlparser_p.h"
+
+class QmlDomDocumentPrivate : public QSharedData
+{
+public:
+ QmlDomDocumentPrivate();
+ QmlDomDocumentPrivate(const QmlDomDocumentPrivate &);
+ ~QmlDomDocumentPrivate();
+
+ QString error;
+ QmlParser::Object *root;
+};
+
+class QmlDomObjectPrivate : public QSharedData
+{
+public:
+ QmlDomObjectPrivate();
+ QmlDomObjectPrivate(const QmlDomObjectPrivate &);
+ ~QmlDomObjectPrivate();
+
+ typedef QList<QPair<QmlParser::Property *, QByteArray> > Properties;
+ Properties properties() const;
+ Properties properties(QmlParser::Property *) const;
+
+ QmlParser::Object *object;
+ bool isVirtualComponent;
+};
+
+class QmlDomPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomPropertyPrivate();
+ QmlDomPropertyPrivate(const QmlDomPropertyPrivate &);
+ ~QmlDomPropertyPrivate();
+
+ QByteArray propertyName;
+ QmlParser::Property *property;
+};
+
+class QmlDomValuePrivate : public QSharedData
+{
+public:
+ QmlDomValuePrivate();
+ QmlDomValuePrivate(const QmlDomValuePrivate &);
+ ~QmlDomValuePrivate();
+
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+};
+
+class QmlDomBasicValuePrivate : public QSharedData
+{
+public:
+ QmlDomBasicValuePrivate();
+ QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &);
+ ~QmlDomBasicValuePrivate();
+
+ QmlParser::Value *value;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
new file mode 100644
index 0000000..63f45b4
--- /dev/null
+++ b/src/declarative/qml/qmlengine.cpp
@@ -0,0 +1,1295 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// XXX ;)
+#define private public
+#include <QMetaProperty>
+#undef private
+
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+
+#ifdef QT_SCRIPTTOOLS_LIB
+#include <QScriptEngineDebugger>
+#endif
+
+#include <QScriptClass>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QList>
+#include <QPair>
+#include <QDebug>
+#include <QMetaObject>
+#include "qml.h"
+#include <qfxperf.h>
+#include <QStack>
+#include "private/qmlbasicscript_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <qmlcomponent.h>
+#include "private/qmlmetaproperty_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(bindValueDebug, QML_BINDVALUE_DEBUG);
+#ifdef QT_SCRIPTTOOLS_LIB
+DEFINE_BOOL_CONFIG_OPTION(debuggerEnabled, QML_DEBUGGER);
+#endif
+
+Q_DECLARE_METATYPE(QmlMetaProperty);
+
+QML_DEFINE_TYPE(QObject,Object);
+
+static QScriptValue qmlMetaProperty_emit(QScriptContext *ctx, QScriptEngine *engine)
+{
+ QmlMetaProperty mp = qscriptvalue_cast<QmlMetaProperty>(ctx->thisObject());
+ if(mp.type() & QmlMetaProperty::Signal)
+ mp.emitSignal();
+ return engine->nullValue();
+}
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+
+struct QmlEngineStack {
+ QmlEngineStack();
+
+ QStack<QmlEngine *> mainThreadEngines;
+ QThread *mainThread;
+
+ QThreadStorage<QStack<QmlEngine *> *> storage;
+
+ QStack<QmlEngine *> *engines();
+};
+
+Q_GLOBAL_STATIC(QmlEngineStack, engineStack);
+
+QmlEngineStack::QmlEngineStack()
+: mainThread(0)
+{
+}
+
+QStack<QmlEngine *> *QmlEngineStack::engines()
+{
+ if(mainThread== 0) {
+ if(!QCoreApplication::instance())
+ return 0;
+ mainThread = QCoreApplication::instance()->thread();
+ }
+
+ // Note: This is very slightly faster than just using the thread storage
+ // for everything.
+ QStack<QmlEngine *> *engines = 0;
+ if(QThread::currentThread() == mainThread) {
+ engines = &mainThreadEngines;
+ } else {
+ engines = storage.localData();
+ if(!engines) {
+ engines = new QStack<QmlEngine *>;
+ storage.setLocalData(engines);
+ }
+ }
+ return engines;
+}
+
+
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
+: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
+ rootComponent(0), networkAccessManager(0), typeManager(e)
+{
+ QScriptValue proto = scriptEngine.newObject();
+ proto.setProperty(QLatin1String("emit"),
+ scriptEngine.newFunction(qmlMetaProperty_emit));
+ scriptEngine.setDefaultPrototype(qMetaTypeId<QmlMetaProperty>(), proto);
+
+ QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get());
+ scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject);
+}
+
+QmlEnginePrivate::~QmlEnginePrivate()
+{
+ delete rootContext;
+ rootContext = 0;
+ delete contextClass;
+ contextClass = 0;
+ delete objectClass;
+ objectClass = 0;
+ delete networkAccessManager;
+ networkAccessManager = 0;
+}
+
+void QmlEnginePrivate::init()
+{
+ contextClass = new QmlContextScriptClass(q);
+ objectClass = new QmlObjectScriptClass(q);
+ rootContext = new QmlContext(q);
+#ifdef QT_SCRIPTTOOLS_LIB
+ if(debuggerEnabled()){
+ debugger = new QScriptEngineDebugger(q);
+ debugger->attachTo(&scriptEngine);
+ }
+#endif
+}
+
+QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
+{
+ QmlContext *old = currentBindContext;
+ currentBindContext = c;
+ return old;
+}
+
+////////////////////////////////////////////////////////////////////
+typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
+Q_GLOBAL_STATIC(FunctionCache, functionCache);
+
+QScriptClass::QueryFlags
+QmlEnginePrivate::queryObject(const QString &propName,
+ uint *id, QObject *obj)
+{
+ QScriptClass::QueryFlags rv = 0;
+
+ QmlMetaProperty prop(obj, propName);
+ 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) {
+ *id = QmlScriptClass::FunctionId;
+ rv |= QScriptClass::HandlesReadAccess;
+ }
+ } else {
+ *id = QmlScriptClass::PropertyId;
+ *id |= prop.save();
+
+ rv |= QScriptClass::HandlesReadAccess;
+ if(prop.isWritable())
+ rv |= QScriptClass::HandlesWriteAccess;
+ }
+
+ return rv;
+}
+
+QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
+ QObject *obj, uint id)
+{
+ if(id == QmlScriptClass::FunctionId) {
+ QScriptValue sobj = scriptEngine.newQObject(obj);
+ QScriptValue func = sobj.property(propName);
+ return func;
+ } else {
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+ if(!prop.isValid())
+ return QScriptValue();
+
+ if(prop.type() & QmlMetaProperty::Signal) {
+ return scriptEngine.newVariant(qVariantFromValue(prop));
+ } else {
+ QVariant var = prop.read();
+ capturedProperties << prop;
+ QObject *varobj = QmlMetaType::toQObject(var);
+ if(!varobj)
+ varobj = qvariant_cast<QObject *>(var);
+ if(varobj) {
+ return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
+ } else {
+ if (var.type() == QVariant::Bool)
+ return QScriptValue(&scriptEngine, var.toBool());
+ return scriptEngine.newVariant(var);
+ }
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlEnginePrivate::contextActivated(QmlContext *)
+{
+ Q_Q(QmlEngine);
+ QmlEngineStack *stack = engineStack();
+ if(!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if(engines)
+ engines->push(q);
+}
+
+void QmlEnginePrivate::contextDeactivated(QmlContext *)
+{
+ QmlEngineStack *stack = engineStack();
+ if(!stack)
+ return;
+ QStack<QmlEngine *> *engines = stack->engines();
+ if(engines) {
+ Q_ASSERT(engines->top() == q_func());
+ engines->pop();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////
+
+bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj)
+{
+ QmlMetaProperty prop(obj, propName);
+
+ if(!prop.isValid())
+ return false;
+
+ capturedProperties << prop;
+
+ if(prop.type() & QmlMetaProperty::Attached) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Attached;
+ cache.attached = prop.d->attachedObject();
+ return true;
+
+ } else if(prop.type() & QmlMetaProperty::Property) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Core;
+ cache.core = prop.property().idx + prop.property().mobj->propertyOffset();
+ cache.coreType = prop.propertyType();
+ return true;
+
+ } else if(prop.type() & QmlMetaProperty::SignalProperty) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::SignalProperty;
+ cache.core = prop.coreIndex();
+ return true;
+
+ } else if(prop.type() & QmlMetaProperty::Signal) {
+
+ cache.object = obj;
+ cache.type = QmlBasicScriptNodeCache::Signal;
+ cache.core = prop.coreIndex();
+ return true;
+
+ }
+
+ return false;
+}
+
+bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context)
+{
+ while(context) {
+ if(context->variantProperties.contains(propName)) {
+ cache.object = 0;
+ cache.type = QmlBasicScriptNodeCache::Variant;
+ cache.context = context;
+ return true;
+ }
+
+ if(context->properties.contains(propName)) {
+ cache.object = context->properties[propName];
+ cache.type = QmlBasicScriptNodeCache::Explicit;
+ return true;
+ }
+
+ foreach(QObject *obj, context->defaultObjects) {
+ if(fetchCache(cache, propName, obj))
+ return true;
+ }
+
+ if(context->parent)
+ context = context->parent->d_func();
+ else
+ context = 0;
+ }
+ return false;
+}
+
+
+/*!
+ \class QmlEngine
+ \brief The QmlEngine class provides an environment for instantiating QML components.
+ \mainclass
+
+ Each QML component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are arranged
+ hierarchically and this hierarchy is managed by the QmlEngine.
+
+ Prior to creating any QML components, an application must have created a
+ QmlEngine to gain access to a QML context. The following example shows how
+ to create a simple Text item.
+
+ \code
+ QmlEngine engine;
+ QmlComponent component("<Text text=\"Hello world!\"/>");
+ QFxItem *item = qobject_cast<QFxItem *>(component.create(&engine));
+
+ //add item to view, etc
+ ...
+ \endcode
+
+ In this case, the Text item will be created in the engine's
+ \l {QmlEngine::rootContext()}{root context}.
+
+ \sa QmlComponent QmlContext
+*/
+
+/*!
+ Create a new QmlEngine with the given \a parent.
+*/
+QmlEngine::QmlEngine(QObject *parent)
+: QObject(*new QmlEnginePrivate(this), parent)
+{
+ Q_D(QmlEngine);
+ d->init();
+
+ qRegisterMetaType<QVariant>("QVariant");
+}
+
+/*!
+ Destroys the QmlEngine.
+
+ Any QmlContext's created on this engine will be invalidated, but not
+ destroyed (unless they are parented to the QmlEngine object).
+*/
+QmlEngine::~QmlEngine()
+{
+}
+
+void QmlEngine::clearComponentCache()
+{
+ Q_D(QmlEngine);
+ d->typeManager.clearCache();
+}
+
+/*!
+ Returns the engine's root context.
+
+ The root context is automatically created by the QmlEngine. Data that
+ should be available to all QML component instances instantiated by the
+ engine should be put in the root context.
+
+ Additional data that should only be available to a subset of component
+ instances should be added to sub-contexts parented to the root context.
+*/
+QmlContext *QmlEngine::rootContext()
+{
+ Q_D(QmlEngine);
+ return d->rootContext;
+}
+
+/*!
+ Returns this engine's active context, or 0 if no context is active on this
+ engine.
+
+ Contexts are activated and deactivated by calling QmlContext::activate() and
+ QmlContext::deactivate() respectively.
+
+ Context activation holds no special semantic, other than it allows types
+ instantiated by QML to access "their" context without having it passed as
+ a parameter in their constructor, as shown below.
+ \code
+ class MyClass : ... {
+ ...
+ MyClass() {
+ qWarning() << "I was instantiated in this context:"
+ << QmlContext::activeContext();
+ }
+ };
+ \endcode
+*/
+QmlContext *QmlEngine::activeContext()
+{
+ Q_D(QmlEngine);
+ if(d->currentBindContext)
+ return d->currentBindContext;
+ else
+ return 0;
+}
+
+/*!
+ Sets the mappings from namespace URIs to URL to \a map.
+
+ \sa nameSpacePaths
+*/
+void QmlEngine::setNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths = map;
+}
+
+/*!
+ Adds mappings (given by \a map) from namespace URIs to URL.
+
+ \sa nameSpacePaths
+*/
+void QmlEngine::addNameSpacePaths(const QMap<QString,QString>& map)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.unite(map);
+}
+
+/*!
+ Adds a mapping from namespace URI \a ns to URL \a path.
+
+ \sa nameSpacePaths
+*/
+void QmlEngine::addNameSpacePath(const QString& ns, const QString& path)
+{
+ Q_D(QmlEngine);
+ d->nameSpacePaths.insertMulti(ns,path);
+}
+
+/*!
+ Returns the mapping from namespace URIs to URLs.
+
+ Namespaces in QML allow types to be specified by a URI,
+ using standard XML namespaces:
+
+ \code
+ <Item xmlns:foo="xyz://abc/def">
+ <foo:Bar/>
+ </Item>
+ \endcode
+
+ Actual QML types can be defined in URLs, in which case a mapping
+ may be made from URIs (such as "xyz://abc/def/Bar.qml" above, to
+ URLs (such as "file:///opt/abcdef/Bar.qml"):
+
+ \code
+ engine->addNameSpacePath("xyz://abc/def","file:///opt/abcdef");
+ \endcode
+
+ If only a prefix of the URI is mapped, the path of the URI is
+ mapped similarly to the URL:
+
+ \code
+ engine->addNameSpacePath("xyz://abc","file:///opt/jkl");
+ \endcode
+
+ In the above case, "xyz://abc/def/Bar.qml" would then map to
+ "file:///opt/jkl/def/Bar.qml".
+
+ \sa componentUrl
+*/
+QMap<QString,QString> QmlEngine::nameSpacePaths() const
+{
+ Q_D(const QmlEngine);
+ return d->nameSpacePaths;
+}
+
+/*!
+ Returns the URL for the component source \a src, as mapped
+ by the nameSpacePaths(), resolved relative to \a baseUrl.
+
+ \sa nameSpacePaths
+*/
+QUrl QmlEngine::componentUrl(const QUrl& src, const QUrl& baseUrl) const
+{
+ Q_D(const QmlEngine);
+
+ // Find the most-specific namespace matching src.
+ // For files, multiple paths can be given, the first found is used.
+ QUrl r;
+ QMap<QString, QString>::const_iterator i = d->nameSpacePaths.constBegin();
+ QString rns=QLatin1String(":"); // ns of r, if file found, initial an imposible namespace
+ QString srcstring = src.toString();
+ while (i != d->nameSpacePaths.constEnd()) {
+ QString ns = i.key();
+ QString path = i.value();
+ if (ns != rns) {
+ if (srcstring.startsWith(ns) && (ns.length()==0 || srcstring[ns.length()]==QLatin1Char('/'))) {
+ QString file = ns.length()==0 ? srcstring : srcstring.mid(ns.length()+1);
+ QUrl cr = baseUrl.resolved(QUrl(path + QLatin1String("/") + file));
+ QString lf = cr.toLocalFile();
+ if (lf.isEmpty() || QFile::exists(lf)) {
+ r = cr;
+ rns = ns;
+ }
+ }
+ }
+ ++i;
+ }
+ if (r.isEmpty())
+ r = baseUrl.resolved(src);
+ return r;
+}
+
+/*!
+ Sets the common QNetworkAccessManager, \a network, used by all QML elements instantiated
+ by this engine.
+
+ Any previously set manager is deleted and \a network is owned by the QmlEngine. This
+ method should only be called before any QmlComponents are instantiated.
+*/
+void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network)
+{
+ Q_D(QmlEngine);
+ delete d->networkAccessManager;
+ d->networkAccessManager = network;
+}
+
+/*!
+ Returns the common QNetworkAccessManager used by all QML elements instantiated by
+ this engine.
+
+ The default implements no caching, cookiejar, etc., just a default
+ QNetworkAccessManager.
+*/
+QNetworkAccessManager *QmlEngine::networkAccessManager() const
+{
+ Q_D(const QmlEngine);
+ if(!d->networkAccessManager)
+ d->networkAccessManager = new QNetworkAccessManager;
+ return d->networkAccessManager;
+}
+
+/*! \internal */
+QScriptEngine *QmlEngine::scriptEngine()
+{
+ Q_D(QmlEngine);
+ return &d->scriptEngine;
+}
+
+/*!
+ Returns the currently active QmlEngine.
+
+ The active engine is the engine associated with the last activated
+ QmlContext. This method is thread-safe - the "active" engine is maintained
+ independently for each thread.
+*/
+QmlEngine *QmlEngine::activeEngine()
+{
+ QmlEngineStack *stack = engineStack();
+ if(!stack) return 0;
+
+ QStack<QmlEngine *> *engines = stack->engines();
+ if(!engines) {
+ qWarning("QmlEngine::activeEngine() cannot be called before the construction of QCoreApplication");
+ return 0;
+ }
+
+ if(engines->isEmpty())
+ return 0;
+ else
+ return engines->top();
+}
+
+
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b)
+: q(b), ctxt(0), sseData(0), proxy(0), me(0), trackChange(false)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, void *expr, QmlRefCount *rc)
+: q(b), ctxt(0), sse((const char *)expr, rc), sseData(0), proxy(0), me(0), trackChange(true)
+{
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpression *b, const QString &expr, bool ssecompile)
+: q(b), ctxt(0), expression(expr), sseData(0), proxy(0), me(0), trackChange(true)
+{
+ if(ssecompile) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindCompile> pt;
+#endif
+ sse.compile(expr.toLatin1());
+ }
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ sse.deleteScriptState(sseData);
+ sseData = 0;
+ delete proxy;
+}
+
+/*!
+ Create an invalid QmlExpression.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+ */
+QmlExpression::QmlExpression()
+: d(new QmlExpressionPrivate(this))
+{
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
+ QmlRefCount *rc, QObject *me)
+: d(new QmlExpressionPrivate(this, expr, rc))
+{
+ d->ctxt = ctxt;
+ d->me = me;
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
+ QObject *me, bool ssecompile)
+: d(new QmlExpressionPrivate(this, expr, ssecompile))
+{
+ d->ctxt = ctxt;
+ d->me = me;
+}
+
+/*!
+ Create a QmlExpression object.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope)
+: d(new QmlExpressionPrivate(this, expression, true))
+{
+ d->ctxt = ctxt;
+ d->me = scope;
+}
+
+/*!
+ Destroy the QmlExpression instance.
+*/
+QmlExpression::~QmlExpression()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Returns the QmlEngine this expression is associated with, or 0 if there
+ is no association or the QmlEngine has been destroyed.
+*/
+QmlEngine *QmlExpression::engine() const
+{
+ return d->ctxt->engine();
+}
+
+/*!
+ Returns teh QmlContext this expression is associated with, or 0 if there
+ is no association or the QmlContext has been destroyed.
+*/
+QmlContext *QmlExpression::context() const
+{
+ return d->ctxt;
+}
+
+/*!
+ Returns the expression string.
+*/
+QString QmlExpression::expression() const
+{
+ if(d->sse.isValid())
+ return QLatin1String(d->sse.expression());
+ else
+ return d->expression;
+}
+
+/*!
+ Clear the expression.
+*/
+void QmlExpression::clearExpression()
+{
+ setExpression(QString());
+}
+
+/*!
+ Set the expression to \a expression.
+*/
+void QmlExpression::setExpression(const QString &expression)
+{
+ if(d->sseData) {
+ d->sse.deleteScriptState(d->sseData);
+ d->sseData = 0;
+ }
+
+ delete d->proxy; d->proxy = 0;
+
+ d->expression = expression;
+
+ if(d->expression.isEmpty())
+ d->sse.clear();
+ else
+ d->sse.compile(expression.toLatin1());
+}
+
+/*!
+ Called by QmlExpression each time the expression value changes from the
+ last time it was evaluated. The expression must have been evaluated at
+ least once (by calling QmlExpression::value()) before this callback will
+ be made.
+
+ The default implementation does nothing.
+*/
+void QmlExpression::valueChanged()
+{
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+void BindExpressionProxy::changed()
+{
+ e->valueChanged();
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpression::value()
+{
+ if(bindValueDebug())
+ qWarning() << "QmlEngine: Evaluating:" << expression();
+ QVariant rv;
+ if(!d->ctxt || (!d->sse.isValid() && d->expression.isEmpty()))
+ return rv;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValue> perf;
+#endif
+
+ QmlBasicScript::CacheState cacheState = QmlBasicScript::Reset;
+
+ QmlEnginePrivate *ep = engine()->d_func();
+ QmlExpression *lastCurrentExpression = ep->currentExpression;
+ ep->currentExpression = this;
+ if(d->sse.isValid()) {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
+#endif
+
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ if(!d->sseData)
+ d->sseData = d->sse.newScriptState();
+ rv = d->sse.run(context(), d->sseData, &cacheState);
+
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ } else {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
+#endif
+ context()->d_func()->defaultObjects.insert(context()->d_func()->highPriorityCount, d->me);
+
+ QScriptEngine *scriptEngine = engine()->scriptEngine();
+ QScriptValueList oldScopeChain = scriptEngine->currentContext()->scopeChain();
+ for (int i = 0; i < oldScopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = context()->d_func()->scopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(context()->d_func()->scopeChain.at(i));
+ }
+ QScriptValue svalue = scriptEngine->evaluate(expression());
+ context()->d_func()->defaultObjects.removeAt(context()->d_func()->highPriorityCount);
+ if(svalue.isArray()) {
+ int length = svalue.property(QLatin1String("length")).toInt32();
+ if(length && svalue.property(0).isObject()) {
+ 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;
+ }
+ }
+ rv = QVariant::fromValue(list);
+ }
+ } /*else if (svalue.isVariant()) {
+ rv = svalue.toVariant();
+ }*/ else if (svalue.isObject()) {
+ QScriptValue objValue = svalue.data();
+ if (objValue.isValid())
+ rv = objValue.toVariant();
+ }
+ if(rv.isNull()) {
+ rv = svalue.toVariant();
+ }
+
+ for (int i = 0; i < context()->d_func()->scopeChain.size(); ++i) {
+ scriptEngine->currentContext()->popScope();
+ }
+ for (int i = oldScopeChain.size() - 1; i > -1; --i) {
+ scriptEngine->currentContext()->pushScope(oldScopeChain.at(i));
+ }
+ }
+ ep->currentExpression = lastCurrentExpression;
+
+ if(cacheState != QmlBasicScript::NoChange) {
+ if(cacheState != QmlBasicScript::Incremental && d->proxy) {
+ delete d->proxy;
+ d->proxy = 0;
+ }
+
+ if(trackChange() && ep->capturedProperties.count()) {
+ if(!d->proxy)
+ d->proxy = new BindExpressionProxy(this);
+
+ static int changedIndex = -1;
+ if(changedIndex == -1)
+ changedIndex = BindExpressionProxy::staticMetaObject.indexOfSlot("changed()");
+
+ if(bindValueDebug())
+ qWarning() << " Depends on:";
+
+ for(int ii = 0; ii < ep->capturedProperties.count(); ++ii) {
+ const QmlMetaProperty &prop =
+ ep->capturedProperties.at(ii);
+
+ if(prop.hasChangedNotifier()) {
+ prop.connectNotifier(d->proxy, changedIndex);
+ if(bindValueDebug())
+ qWarning() << " property"
+ << prop.name()
+ << prop.object()
+ << prop.object()->metaObject()->superClass()->className();
+ } else if(bindValueDebug()) {
+ qWarning() << " non-subscribable property"
+ << prop.name()
+ << prop.object()
+ << prop.object()->metaObject()->superClass()->className();
+ }
+ }
+ }
+ }
+ ep->capturedProperties.clear();
+
+ if(bindValueDebug())
+ qWarning() << " Result:" << rv
+ << "(SSE: " << d->sse.isValid() << ")";
+ return rv;
+}
+
+/*!
+ Returns true if the expression results in a constant value.
+ QmlExpression::value() must have been invoked at least once before the
+ return from this method is valid.
+ */
+bool QmlExpression::isConstant() const
+{
+ return d->proxy == 0;
+}
+
+/*!
+ Returns true if the changes are tracked in the expression's value.
+*/
+bool QmlExpression::trackChange() const
+{
+ return d->trackChange;
+}
+
+/*!
+ Set whether changes are tracked in the expression's value to \a trackChange.
+
+ If true, the QmlExpression will monitor properties involved in the
+ expression's evaluation, and call QmlExpression::valueChanged() if they have
+ changed. This allows an application to ensure that any value associated
+ with the result of the expression remains up to date.
+
+ If false, the QmlExpression will not montitor properties involved in the
+ expression's evaluation, and QmlExpression::valueChanged() will never be
+ called. This is more efficient if an application wants a "one off"
+ evaluation of the expression.
+
+ By default, trackChange is true.
+*/
+void QmlExpression::setTrackChange(bool trackChange)
+{
+ d->trackChange = trackChange;
+}
+
+/*!
+ Returns the expression's scope object, if provided, otherwise 0.
+
+ In addition to data provided by the expression's QmlContext, the scope
+ object's properties are also in scope during the expression's evaluation.
+*/
+QObject *QmlExpression::scopeObject() const
+{
+ return d->me;
+}
+
+/*!
+ \class QmlExpression
+ \brief The QmlExpression class evaluates ECMAScript in a QML context.
+*/
+
+/*!
+ \class QmlExpressionObject
+ \brief The QmlExpressionObject class extends QmlExpression with signals and slots.
+
+ To remain as lightweight as possible, QmlExpression does not inherit QObject
+ and consequently cannot use signals or slots. For the cases where this is
+ more convenient in an application, QmlExpressionObject can be used instead.
+
+ QmlExpressionObject behaves identically to QmlExpression, except that the
+ QmlExpressionObject::value() method is a slot, and the
+ QmlExpressionObject::valueChanged() callback is a signal.
+*/
+/*!
+ Create a QmlExpression with the specified \a parent.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+*/
+QmlExpressionObject::QmlExpressionObject(QObject *parent)
+: QObject(parent)
+{
+}
+
+/*!
+ Create a QmlExpressionObject with the specified \a parent.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expression, QObject *scope, QObject *parent)
+: QObject(parent), QmlExpression(ctxt, expression, scope, true)
+{
+}
+
+/*! \internal */
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, const QString &expr, QObject *scope, bool sse)
+: QmlExpression(ctxt, expr, scope, sse)
+{
+}
+
+/*! \internal */
+QmlExpressionObject::QmlExpressionObject(QmlContext *ctxt, void *d, QmlRefCount *rc, QObject *me)
+: QmlExpression(ctxt, d, rc, me)
+{
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+*/
+QVariant QmlExpressionObject::value()
+{
+ return QmlExpression::value();
+}
+
+/*!
+ \fn void QmlExpressionObject::valueChanged()
+
+ Emitted each time the expression value changes from the last time it was
+ evaluated. The expression must have been evaluated at least once (by
+ calling QmlExpressionObject::value()) before this signal will be emitted.
+*/
+
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(bindengine->scriptEngine()), engine(bindengine)
+{
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ 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);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ContextQuery> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+ QueryFlags rv = 0;
+
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query Context:" << propName << bindContext;
+#endif
+
+ *id = InvalidId;
+ if (bindContext->d_func()->variantProperties.contains(propName)) {
+ rv |= HandlesReadAccess;
+ *id = VariantPropertyId;
+ } else if (bindContext->d_func()->properties.contains(propName)) {
+ rv |= HandlesReadAccess;
+ *id = ObjectListPropertyId;
+ }
+
+ for(int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
+ rv = engine->d_func()->queryObject(propName, id,
+ bindContext->d_func()->defaultObjects.at(ii));
+ if(rv)
+ *id |= (ii << 24);
+ }
+
+ return rv;
+}
+
+QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ContextProperty> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Context Property:" << propName << bindContext;
+#endif
+
+ uint basicId = id & QmlScriptClass::ClassIdMask;
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+
+ switch (basicId) {
+ case VariantPropertyId:
+ {
+ QString propName = name.toString();
+ QScriptValue rv = scriptEngine->newVariant(bindContext->d_func()->variantProperties[propName]);
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Context Property: Resolved property" << propName
+ << "to context variant property list" << bindContext <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+ case ObjectListPropertyId:
+ {
+ QString propName = name.toString();
+ QObject *o = bindContext->d_func()->properties[propName];
+ QScriptValue rv = scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newVariant(QVariant::fromValue(o)));
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Context Property: Resolved property" << propName
+ << "to context object property list" << bindContext <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+ default:
+ {
+ int objId = (id & ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objId);
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj,
+ id & ~QmlScriptClass::ClassIdSelectorMask);
+ if(rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to context default object" << bindContext << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+ break;
+ }
+ }
+
+ return QScriptValue();
+}
+
+void QmlContextScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectSetProperty> perf;
+#endif
+ QmlContext *bindContext =
+ static_cast<QmlContext*>(object.data().toQObject());
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24;
+ QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx);
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+/////////////////////////////////////////////////////////////
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+ : QmlScriptClass(bindEngine)
+{
+ engine = bindEngine;
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectQuery> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+ QueryFlags rv = 0;
+ QString propName = name.toString();
+
+#ifdef PROPERTY_DEBUG
+ qWarning() << "Query QmlObject:" << propName << obj;
+#endif
+
+ if (obj)
+ rv = engine->d_func()->queryObject(propName, id, obj);
+
+ return rv;
+}
+
+QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectProperty> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "QmlObject Property:" << propName << obj;
+#endif
+
+ QScriptValue rv = engine->d_func()->propertyObject(name, obj, id);
+ if(rv.isValid()) {
+#ifdef PROPERTY_DEBUG
+ qWarning() << "~Property: Resolved property" << propName
+ << "to object" << obj <<". Value:" << rv.toVariant();
+#endif
+ return rv;
+ }
+
+ return QScriptValue();
+}
+
+void QmlObjectScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::ObjectSetProperty> perf;
+#endif
+ QObject *obj = object.data().toQObject();
+
+#ifdef PROPERTY_DEBUG
+ QString propName = name.toString();
+ qWarning() << "Set QmlObject Property" << name.toString() << value.toVariant();
+#endif
+
+ QScriptEngine *scriptEngine = engine->scriptEngine();
+ QScriptValue oldact = scriptEngine->currentContext()->activationObject();
+ scriptEngine->currentContext()->setActivationObject(scriptEngine->globalObject());
+
+ QmlMetaProperty prop;
+ prop.restore(id, obj);
+
+ QVariant v;
+ QObject *data = value.data().toQObject();
+ if (data) {
+ v = QVariant::fromValue(data);
+ } else {
+ v = value.toVariant();
+ }
+ prop.write(v);
+
+ scriptEngine->currentContext()->setActivationObject(oldact);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
new file mode 100644
index 0000000..086595a
--- /dev/null
+++ b/src/declarative/qml/qmlengine.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QMLENGINE_H
+#define QMLENGINE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlComponent;
+class QmlEnginePrivate;
+class QmlExpression;
+class QmlContext;
+class QUrl;
+class QScriptEngine;
+class QNetworkAccessManager;
+class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
+{
+ Q_OBJECT
+public:
+ QmlEngine(QObject *p = 0);
+ virtual ~QmlEngine();
+
+ static QmlEngine *activeEngine();
+
+ QmlContext *rootContext();
+ QmlContext *activeContext();
+
+ void clearComponentCache();
+
+ void setNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePaths(const QMap<QString,QString>& map);
+ void addNameSpacePath(const QString&,const QString&);
+ QMap<QString,QString> nameSpacePaths() const;
+ QUrl componentUrl(const QUrl& src, const QUrl& baseUrl) const;
+
+ void setNetworkAccessManager(QNetworkAccessManager *);
+ QNetworkAccessManager *networkAccessManager() const;
+
+private:
+ // LK: move to the private class
+ QScriptEngine *scriptEngine();
+ friend class QFxItem; // XXX
+ friend class QmlScriptPrivate;
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlScriptClass;
+ friend class QmlContext;
+ friend class QmlContextPrivate;
+ friend class QmlExpression;
+ friend class QmlBasicScript;
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlContextScriptClass; //###
+ friend class QmlObjectScriptClass; //###
+ Q_DECLARE_PRIVATE(QmlEngine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLENGINE_H
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
new file mode 100644
index 0000000..b72c680
--- /dev/null
+++ b/src/declarative/qml/qmlengine_p.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** 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 QMLENGINE_P_H
+#define QMLENGINE_P_H
+
+#include <QScriptClass>
+#include <QScriptValue>
+#include <QScriptString>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <private/qobject_p.h>
+#include <private/qmlclassfactory_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <qml.h>
+#include <qmlbasicscript.h>
+#include <qmlcontext.h>
+#include <qmlengine.h>
+#include <qmlexpression.h>
+#include <QtScript/qscriptengine.h>
+
+QT_BEGIN_NAMESPACE
+class QmlContext;
+class QmlEngine;
+class QmlContextPrivate;
+class QmlExpression;
+class QmlBasicScriptNodeCache;
+class QmlContextScriptClass;
+class QmlObjectScriptClass;
+class QScriptEngineDebugger;
+class QNetworkReply;
+class QNetworkAccessManager;
+
+class QmlEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngine)
+public:
+ QmlEnginePrivate(QmlEngine *);
+ ~QmlEnginePrivate();
+
+ void init();
+
+ void contextActivated(QmlContext *);
+ void contextDeactivated(QmlContext *);
+
+ bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *);
+ bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context);
+
+ QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *);
+ QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
+
+ QList<QmlMetaProperty> capturedProperties;
+
+ QmlContext *rootContext;
+ QmlContext *currentBindContext;
+ QmlExpression *currentExpression;
+ QmlEngine *q;
+#ifdef QT_SCRIPTTOOLS_LIB
+ QScriptEngineDebugger *debugger;
+#endif
+
+ QmlContextScriptClass *contextClass;
+ QmlObjectScriptClass *objectClass;
+
+ QmlContext *setCurrentBindContext(QmlContext *);
+ QStack<QmlContext *> activeContexts;
+
+ QScriptEngine scriptEngine;
+
+ QList<QmlBindableValue *> currentBindValues;
+ QList<QmlParserStatus *> currentParserStatus;
+ QmlComponent *rootComponent;
+ mutable QNetworkAccessManager *networkAccessManager;
+
+ QmlCompositeTypeManager typeManager;
+ QMap<QString,QString> nameSpacePaths;
+};
+
+
+class BindExpressionProxy : public QObject
+{
+Q_OBJECT
+public:
+ BindExpressionProxy(QmlExpression *be)
+ :e(be)
+ {
+ }
+
+private:
+ QmlExpression *e;
+
+private Q_SLOTS:
+ void changed();
+};
+
+class QmlScriptClass : public QScriptClass
+{
+public:
+ enum ClassId
+ {
+ InvalidId = -1,
+
+ ObjectListPropertyId = 0xC0000000,
+ FunctionId = 0x80000000,
+ VariantPropertyId = 0x40000000,
+ PropertyId = 0x00000000,
+
+ ClassIdMask = 0xC0000000,
+
+ ClassIdSelectorMask = 0x3F000000,
+ };
+
+ QmlScriptClass(QmlEngine *);
+
+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 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 QmlExpressionPrivate
+{
+public:
+ QmlExpressionPrivate(QmlExpression *);
+ QmlExpressionPrivate(QmlExpression *, const QString &expr, bool);
+ QmlExpressionPrivate(QmlExpression *, void *expr, QmlRefCount *rc);
+ ~QmlExpressionPrivate();
+
+ QmlExpression *q;
+ QmlContext *ctxt;
+ QString expression;
+ QmlBasicScript sse;
+ void *sseData;
+ BindExpressionProxy *proxy;
+ QObject *me;
+ bool trackChange;
+};
+QT_END_NAMESPACE
+
+#endif // QMLENGINE_P_H
+
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
new file mode 100644
index 0000000..4f9502b
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 QMLEXPRESSION_H
+#define QMLEXPRESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlRefCount;
+class QmlEngine;
+class QmlContext;
+class QmlExpressionPrivate;
+class QmlBasicScript;
+class Q_DECLARATIVE_EXPORT QmlExpression
+{
+public:
+ QmlExpression();
+ QmlExpression(QmlContext *, const QString &, QObject *);
+ QmlExpression(QmlContext *, const QString &, QObject *, bool);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me);
+ virtual ~QmlExpression();
+
+ QmlEngine *engine() const;
+ QmlContext *context() const;
+
+ QString expression() const;
+ void clearExpression();
+ virtual void setExpression(const QString &);
+ QVariant value();
+ bool isConstant() const;
+
+ bool trackChange() const;
+ void setTrackChange(bool);
+
+ QObject *scopeObject() const;
+
+protected:
+ virtual void valueChanged();
+
+private:
+ friend class BindExpressionProxy;
+ QmlExpressionPrivate *d;
+};
+
+// LK: can't we merge with QmlExpression????
+class Q_DECLARATIVE_EXPORT QmlExpressionObject : public QObject,
+ public QmlExpression
+{
+ Q_OBJECT
+public:
+ QmlExpressionObject(QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, const QString &, QObject *scope, QObject *parent = 0);
+ QmlExpressionObject(QmlContext *, const QString &, QObject *scope, bool);
+ QmlExpressionObject(QmlContext *, void *, QmlRefCount *, QObject *);
+
+public Q_SLOTS:
+ QVariant value();
+
+Q_SIGNALS:
+ void valueChanged();
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXPRESSION_H
+
diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp
new file mode 100644
index 0000000..dc7f44c
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 "qmlinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlInfo
+ \brief The QmlInfo class prints warnings messages that include the file and line number for QML types.
+
+ When QML types display warning messages, it improves tracibility if they include the
+ QML file and line number on which the particular instance was instantiated.
+
+ QmlInfo statements work just like regular Qt qDebug() statements. To include the file
+ and line number, an object must be passed. If the file and line number is not available
+ for that instance (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(this) << "component property is a write-once property";
+ \endcode
+
+ prints
+
+ \code
+ QML ComponentInstance (unknown location): component property is a write-once property
+ \endcode
+*/
+
+/*!
+ Construct a QmlInfo, using \a object for file and line number information.
+*/
+QmlInfo::QmlInfo(QObject *object)
+: QDebug(QtWarningMsg)
+{
+ *this << "QML";
+ if(object)
+ *this << object->metaObject()->className();
+ *this << "(unknown location):";
+}
+
+/*!
+ \internal
+*/
+QmlInfo::~QmlInfo()
+{
+}
+
+/*!
+ \fn QmlInfo qmlInfo(QObject *me)
+ \internal
+
+ XXX - how do we document these?
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h
new file mode 100644
index 0000000..da8144c
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QMLINFO_H
+#define QMLINFO_H
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlInfo : public QDebug
+{
+public:
+ QmlInfo(QObject *);
+ ~QmlInfo();
+};
+
+Q_DECLARATIVE_EXPORT inline QmlInfo qmlInfo(QObject *me)
+{
+ return QmlInfo(me);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLINFO_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
new file mode 100644
index 0000000..9938022
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** 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 "private/qmlinstruction_p.h"
+#include "private/qmlcompiledcomponent_p.h"
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+void QmlCompiledComponent::dump(QmlInstruction *instr, int idx)
+{
+ QByteArray lineNumber = QByteArray::number(instr->line);
+ if(instr->line == (unsigned short)-1)
+ lineNumber = "NA";
+ const char *line = lineNumber.constData();
+
+ switch(instr->type) {
+ case QmlInstruction::Init:
+ qWarning() << idx << "\t" << line << "\t" << "INIT\t\t\t" << instr->init.dataSize;
+ break;
+ case QmlInstruction::CreateObject:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::CreateCustomObject:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE_CUSTOM\t\t" << instr->createCustom.type << "\t" << instr->createCustom.data << "\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::SetId:
+ qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t" << instr->setId.save << "\t\t" << primitives.at(instr->setId.value);
+ break;
+ case QmlInstruction::SetDefault:
+ qWarning() << idx << "\t" << line << "\t" << "SET_DEFAULT";
+ break;
+ case QmlInstruction::CreateComponent:
+ 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;
+ break;
+ case QmlInstruction::StoreReal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_REAL\t\t" << instr->storeReal.propertyIndex << "\t" << instr->storeReal.value;
+ break;
+ case QmlInstruction::StoreInteger:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
+ break;
+ case QmlInstruction::StoreBool:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
+ break;
+ case QmlInstruction::StoreString:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreColor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t" << QString::number(instr->storeColor.value, 16);
+ break;
+ case QmlInstruction::StoreDate:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
+ break;
+ case QmlInstruction::StoreTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex;
+ break;
+ case QmlInstruction::StoreDateTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex;
+ break;
+ case QmlInstruction::StorePoint:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StorePointF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSize:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSizeF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreRect:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreRectF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreVariant:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex << "\t" << instr->storeObject.cast;
+ break;
+ case QmlInstruction::AssignCustomType:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
+ case QmlInstruction::StoreSignal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
+ break;
+ case QmlInstruction::AssignConstant:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CONSTANT\t" << instr->assignConstant.property << "\t" << instr->assignConstant.constant << "\t\t" << datas.at(instr->assignConstant.property) << primitives.at(instr->assignConstant.constant);
+ break;
+ case QmlInstruction::AssignSignal:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL\t\t" << instr->assignSignal.signal << "\t" << instr->assignSignal.value << "\t\t" << datas.at(instr->assignSignal.signal) << primitives.at(instr->assignSignal.value);
+ break;
+ case QmlInstruction::AssignSignalObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
+ break;
+ case QmlInstruction::AssignBinding:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property) << primitives.at(instr->assignBinding.value);
+ break;
+ case QmlInstruction::AssignCompiledBinding:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << datas.at(instr->assignBinding.property);
+ break;
+ case QmlInstruction::AssignValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t\t\t" << datas.at(instr->assignValueSource.property);
+ break;
+ case QmlInstruction::StoreBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BINDING\t\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context << primitives.at(instr->assignBinding.value);
+ break;
+ case QmlInstruction::StoreCompiledBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property;
+ break;
+ case QmlInstruction::TryBeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "TRY_BEGIN";
+ break;
+ case QmlInstruction::BeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
+ break;
+ case QmlInstruction::TryCompleteObject:
+ qWarning() << idx << "\t" << line << "\t" << "TRY_COMPLETE";
+ break;
+ case QmlInstruction::CompleteObject:
+ qWarning() << idx << "\t" << line << "\t" << "COMPLETE\t\t" << instr->complete.castValue;
+ break;
+ case QmlInstruction::AssignObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT\t\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property));
+ break;
+ case QmlInstruction::AssignObjectList:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property));
+ break;
+ case QmlInstruction::FetchAttached:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.idx << "\t\t\t" << primitives.at(instr->fetchAttached.idx);
+ break;
+ case QmlInstruction::FetchQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type;
+ break;
+ case QmlInstruction::FetchQList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::ResolveFetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "RESOLVE_FETCH\t\t" << instr->fetch.property << "\t\t\t" << datas.at(instr->fetch.property);
+ break;
+ case QmlInstruction::PopFetchedObject:
+ qWarning() << idx << "\t" << line << "\t" << "POP";
+ break;
+ case QmlInstruction::PopQList:
+ qWarning() << idx << "\t" << line << "\t" << "POP_QLIST";
+ break;
+ case QmlInstruction::NoOp:
+ qWarning() << idx << "\t" << line << "\t" << "NOOP";
+ break;
+ case QmlInstruction::PushProperty:
+ qWarning() << idx << "\t" << line << "\t" << "PUSH_PROPERTY" << "\t\t" << instr->pushProperty.property;
+ break;
+ case QmlInstruction::AssignStackObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ break;
+ case QmlInstruction::StoreStackObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STACK_OBJ" << "\t" << instr->assignStackObject.property << "\t" << instr->assignStackObject.object;
+ break;
+ default:
+ qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION";
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
new file mode 100644
index 0000000..40a0b84
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** 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 QMLINSTRUCTION_P_H
+#define QMLINSTRUCTION_P_H
+
+#include <qfxglobal.h>
+
+
+QT_BEGIN_NAMESPACE
+class QmlCompiledComponent;
+class Q_DECLARATIVE_EXPORT QmlInstruction
+{
+public:
+ enum Type {
+ //
+ // Object Creation
+ //
+ // CreateObject - Create a new object instance and push it on the
+ // object stack
+ // SetId - Set the id of the object on the top of the object stack
+ // SetDefault - Sets the instance on the top of the object stack to
+ // be the context's default object.
+ // StoreMetaObject - Assign the dynamic metaobject to object on the
+ // top of the stack.
+ Init, /* init */
+ CreateObject, /* create */
+ CreateCustomObject, /* createCustom */
+ SetId, /* setId */
+ SetDefault,
+ CreateComponent, /* createComponent */
+ StoreMetaObject, /* storeMeta */
+
+ //
+ // Precomputed single assignment
+ //
+ // StoreReal - Store a qreal in a core property
+ // StoreInteger - Store a int or uint in a core property
+ // StoreBool - Store a bool in a core property
+ // StoreString - Store a QString in a core property
+ // StoreColor - Store a QColor in a core property
+ // StoreDate - Store a QDate in a core property
+ // StoreTime - Store a QTime in a core property
+ // StoreDateTime - Store a QDateTime in a core property
+ // StoreVariant - Store a QVariant in a core property
+ // StoreObject - Pop the object on the top of the object stack and
+ // store it in a core property
+ StoreReal, /* storeReal */
+ StoreInstructionsStart = StoreReal,
+ StoreInteger, /* storeInteger */
+ StoreBool, /* storeBool */
+ StoreString, /* storeString */
+ StoreColor, /* storeColor */
+ StoreDate, /* storeDate */
+ StoreTime, /* storeTime */
+ StoreDateTime, /* storeDateTime */
+ StorePoint, /* storeRealPair */
+ StorePointF, /* storeRealPair */
+ StoreSize, /* storeRealPair */
+ StoreSizeF, /* storeRealPair */
+ StoreRect, /* storeRect */
+ StoreRectF, /* storeRect */
+ StoreVariant, /* storeString */
+ StoreObject, /* storeObject */
+ StoreInstructionsEnd = StoreObject,
+
+ StoreSignal, /* storeSignal */
+
+ StoreObjectQmlList,
+
+ // XXX need to handle storing objects in variants
+
+ //
+ // Unresolved single assignment
+ //
+ // AssignConstant - Store a value in a property. Will resolve into
+ // a Store* instruction.
+ // AssignSignal - Set a signal handler on the property. Will resolve
+ // into a Store*Signal instruction.
+ AssignConstant, /* assignConstant */
+ AssignSignal, /* assignSignal */
+ AssignSignalObject, /* assignSignalObject */
+ AssignCustomType, /* assignCustomType */
+
+ AssignBinding, /* assignBinding */
+ AssignCompiledBinding, /* assignBinding */
+ AssignValueSource, /* assignValueSource */
+ StoreBinding, /* assignBinding */
+ StoreCompiledBinding, /* assignBinding */
+ StoreValueSource, /* assignValueSource */
+
+ TryBeginObject,
+ BeginObject, /* begin */
+ TryCompleteObject,
+ CompleteObject, /* complete */
+
+ AssignObject, /* assignObject */
+ AssignObjectList, /* assignObject */
+
+ FetchAttached, /* fetchAttached */
+ FetchQmlList, /* fetchQmlList */
+ FetchQList, /* fetch */
+ FetchObject, /* fetch */
+ ResolveFetchObject, /* fetch */
+
+ //
+ // Stack manipulation
+ //
+ // PopFetchedObject - Remove an object from the object stack
+ // PopQList - Remove a list from the list stack
+ PopFetchedObject,
+ PopQList,
+
+ //
+ // Expression optimizations
+ //
+ // PushProperty - Save the property for later use
+ // AssignStackObject - Assign the stack object
+ // StoreStackObject - Assign the stack object (no checks)
+ PushProperty, /* pushProperty */
+ AssignStackObject, /* assignStackObject */
+ StoreStackObject, /* assignStackObject */
+
+
+ //
+ // Miscellaneous
+ //
+ // NoOp - Do nothing
+ NoOp
+ };
+ Type type;
+ unsigned short line;
+ union {
+ struct {
+ int dataSize;
+ } init;
+ struct {
+ int type;
+ } create;
+ struct {
+ int data;
+ } storeMeta;
+ struct {
+ int type;
+ int data;
+ } createCustom;
+ struct {
+ int value;
+ int save;
+ } setId;
+ struct {
+ int property;
+ int constant;
+ } assignConstant;
+ struct {
+ int property;
+ int castValue;
+ } assignObject;
+ struct {
+ int property;
+ } assignValueSource;
+ struct {
+ int property;
+ int value;
+ short context;
+ short category;
+ } assignBinding;
+ struct {
+ int property;
+ bool isObject;
+ } fetch;
+ struct {
+ int property;
+ int type;
+ } fetchQmlList;
+ struct {
+ int castValue;
+ } complete;
+ struct {
+ int castValue;
+ } begin;
+ struct {
+ int propertyIndex;
+ float value;
+ } storeReal;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeInteger;
+ struct {
+ int propertyIndex;
+ bool value;
+ } storeBool;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeString;
+ struct {
+ int propertyIndex;
+ unsigned int value;
+ } storeColor;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeDate;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeDateTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRealPair;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRect;
+ struct {
+ int propertyIndex;
+ int cast;
+ } storeObject;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } assignCustomType;
+ struct {
+ int signalIndex;
+ int value;
+ } storeSignal;
+ struct {
+ int signal;
+ int value;
+ } assignSignal;
+ struct {
+ int signal;
+ } assignSignalObject;
+ struct {
+ int count;
+ } createComponent;
+ struct {
+ int idx;
+ } fetchAttached;
+ struct {
+ int property;
+ } pushProperty;
+ struct {
+ int property;
+ int object;
+ } assignStackObject;
+ };
+
+ void dump(QmlCompiledComponent *);
+};
+
+#endif // QMLINSTRUCTION_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmllist.h b/src/declarative/qml/qmllist.h
new file mode 100644
index 0000000..3a1e665
--- /dev/null
+++ b/src/declarative/qml/qmllist.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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 QMLLIST_H
+#define QMLLIST_H
+
+#include <QtDeclarative/qmlprivate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<typename T>
+class QmlList : private QmlPrivate::ListInterface
+{
+public:
+ virtual void append(T) = 0;
+ virtual void insert(int, T) = 0;
+ virtual T at(int) const = 0;
+ virtual void clear() = 0;
+ QmlList<T> &operator<<(T t) { append(t); return *this; }
+
+protected:
+ virtual int type() const { return qMetaTypeId<T>(); }
+ virtual void append(void *d) { const T &v = *(T *)d; append(v); }
+ virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); }
+ virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; }
+};
+
+template<typename T>
+class QmlConcreteList : public QList<T>, public QmlList<T>
+{
+public:
+ virtual void append(T v) { QList<T>::append(v); }
+ virtual void insert(int i, T v) { QList<T>::insert(i, v); }
+ virtual void clear() { QList<T>::clear(); }
+ virtual T at(int i) const { return QList<T>::at(i); }
+ virtual void removeAt(int i) { QList<T>::removeAt(i); }
+ virtual int count() const { return QList<T>::count(); }
+};
+
+#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \
+class Qml_ProxyList_ ##ListName : public QmlList<ListType> \
+{ \
+ public: \
+ virtual void removeAt(int idx) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _removeAt(idx); \
+ } \
+ virtual int count() const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _count(); \
+ } \
+ virtual void append(ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _append(v); \
+ } \
+ virtual void insert(int idx, ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _insert(idx, v); \
+ } \
+ virtual ListType at(int idx) const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _at(idx); \
+ } \
+ virtual void clear() \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _clear(); \
+ } \
+}; \
+friend class Qml_ProxyList_ ##ListName ; \
+Qml_ProxyList_##ListName ListName;
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLIST_H
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..79db6ce
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** 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 "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+#include <qml.h>
+#include <qfxperf.h>
+#include <QStringList>
+#include <qmlbindablevalue.h>
+#include <qmlcontext.h>
+#include "qmlboundsignal_p.h"
+#include <math.h>
+#include <QtCore/qdebug.h>
+
+
+QT_BEGIN_NAMESPACE
+
+class QMetaPropertyEx : public QMetaProperty
+{
+public:
+ QMetaPropertyEx()
+ : propertyType(-1) {}
+
+ QMetaPropertyEx(const QMetaProperty &p)
+ : QMetaProperty(p), propertyType(p.userType()) {}
+
+ QMetaPropertyEx(const QMetaPropertyEx &o)
+ : QMetaProperty(o),
+ propertyType(o.propertyType) {}
+
+ QMetaPropertyEx &operator=(const QMetaPropertyEx &o)
+ {
+ static_cast<QMetaProperty *>(this)->operator=(o);
+ propertyType = o.propertyType;
+ return *this;
+ }
+
+ private:
+ friend class QmlMetaProperty;
+ int propertyType;
+};
+
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+}
+
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+// ### not thread safe
+static QHash<const QMetaObject *, QMetaPropertyEx> qmlCacheDefProp;
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ if(!obj)
+ return;
+
+ d->object = obj;
+ QHash<const QMetaObject *, QMetaPropertyEx>::ConstIterator iter =
+ qmlCacheDefProp.find(obj->metaObject());
+ if(iter != qmlCacheDefProp.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyType;
+ } else {
+ QMetaPropertyEx p(QmlMetaType::defaultProperty(obj));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = d->prop.propertyIndex();
+ if(!QObjectPrivate::get(obj)->metaObject)
+ qmlCacheDefProp.insert(obj->metaObject(), d->prop);
+ }
+ if(d->prop.name() != 0) {
+ d->type = Property | Default;
+ d->name = QLatin1String(d->prop.name());
+ }
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property at index \a idx of \a obj.
+
+ The QmlMetaProperty is assigned category \a cat.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, PropertyCategory cat, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->context = ctxt;
+ d->object = obj;
+ d->type = Property;
+ d->category = cat;
+ QMetaPropertyEx p(obj->metaObject()->property(idx));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = idx;
+ if(d->prop.name() != 0)
+ d->name = QLatin1String(d->prop.name());
+}
+
+// ### Not thread safe!!!!
+static QHash<const QMetaObject *, QHash<QString, QMetaPropertyEx> > qmlCacheProps;
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::MetaProperty> perf;
+#endif
+
+ d->context = ctxt;
+ d->name = name;
+ d->object = obj;
+ if(name.isEmpty() || !obj)
+ return;
+
+ if(name.at(0).isUpper()) {
+ // Attached property
+ d->attachedFunc = QmlMetaType::attachedPropertiesFuncId(name.toLatin1());
+ if(d->attachedFunc != -1)
+ d->type = Property | Attached;
+ return;
+ } else if(name.count() >= 3 && name.startsWith(QLatin1String("on")) && name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ d->findSignalInt(obj, signalName);
+ if(d->signal.signature() != 0) {
+ d->type = SignalProperty;
+ return;
+ }
+ }
+
+ // Property
+ QHash<QString, QMetaPropertyEx> &props = qmlCacheProps[obj->metaObject()];
+ QHash<QString, QMetaPropertyEx>::ConstIterator iter = props.find(name);
+ if(iter != props.end()) {
+ d->prop = *iter;
+ d->propType = iter->propertyType;
+ d->coreIdx = iter->propertyIndex();
+ } else {
+ QMetaPropertyEx p = QmlMetaType::property(obj, name.toLatin1().constData());
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = p.propertyIndex();
+ if (!QObjectPrivate::get(obj)->metaObject)
+ props.insert(name, p);
+ }
+ if(d->prop.name() != 0)
+ d->type = Property;
+
+ if(d->type == Invalid) {
+ int sig = findSignal(obj, name.toLatin1());
+ if(sig != -1) {
+ d->signal = obj->metaObject()->method(sig);
+ d->type = Signal;
+ d->coreIdx = sig;
+ }
+ }
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+}
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ if(d->category == Unknown) {
+ int type = propertyType();
+ if(!isValid())
+ d->category = InvalidProperty;
+ else if(type == qMetaTypeId<QmlBindableValue *>())
+ d->category = Bindable;
+ else if(QmlMetaType::isList(type))
+ d->category = List;
+ else if(QmlMetaType::isQmlList(type))
+ d->category = QmlList;
+ else if(QmlMetaType::isObject(type))
+ d->category = Object;
+ else
+ d->category = Normal;
+ }
+ return d->category;
+}
+
+/*!
+ Returns the property category of \a prop.
+*/
+QmlMetaProperty::PropertyCategory
+QmlMetaProperty::propertyCategory(const QMetaProperty &prop)
+{
+ if(prop.name()) {
+ int type = 0;
+ if(prop.type() == QVariant::LastType)
+ type = qMetaTypeId<QVariant>();
+ else if(prop.type() == QVariant::UserType)
+ type = prop.userType();
+ else
+ type = prop.type();
+
+ if(type == qMetaTypeId<QmlBindableValue *>())
+ return Bindable;
+ else if(QmlMetaType::isList(type))
+ return List;
+ else if(QmlMetaType::isQmlList(type))
+ return QmlList;
+ else if(QmlMetaType::isObject(type))
+ return Object;
+ else
+ return Normal;
+ } else {
+ return InvalidProperty;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ if(d->prop.name()) {
+ return d->prop.typeName();
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ return d->prop.name() == other.d->prop.name() &&
+ d->signal.signature() == other.d->signal.signature() &&
+ d->type == other.d->type &&
+ d->object == other.d->object;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ int rv = QVariant::Invalid;
+
+ if(d->prop.name()) {
+ if(d->propType == (int)QVariant::LastType)
+ rv = qMetaTypeId<QVariant>();
+ else
+ rv = d->propType;
+ } else if(d->attachedFunc) {
+ rv = qMetaTypeId<QObject *>();
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ return (Type)d->type;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->name = other.d->name;
+ d->prop = other.d->prop;
+ d->propType = other.d->propType;
+ d->type = other.d->type;
+ d->signal = other.d->signal;
+ d->coreIdx = other.d->coreIdx;
+ d->attachedFunc = other.d->attachedFunc;
+ d->object = other.d->object;
+ d->category = other.d->category;
+ return *this;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ if(propertyCategory() == List || propertyCategory() == QmlList)
+ return true;
+ else if(d->prop.name() != 0)
+ return d->prop.isWritable();
+ else if(type() & SignalProperty)
+ return true;
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if(d->prop.name() != 0)
+ return d->prop.isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Returns all of \a obj's Qt properties.
+*/
+QStringList QmlMetaProperty::properties(QObject *obj)
+{
+ if(!obj)
+ return QStringList();
+
+ QStringList rv;
+ const QMetaObject *mo = obj->metaObject();
+ for(int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty prop = mo->property(ii);
+ rv << QLatin1String(prop.name());
+ }
+
+ return rv;
+}
+
+/*!
+ Return the name of this property.
+*/
+QString QmlMetaProperty::name() const
+{
+ return d->name;
+}
+
+const QMetaProperty &QmlMetaProperty::property() const
+{
+ return d->prop;
+}
+
+/*!
+ Returns the binding associated with this property, or 0 if no binding
+ exists.
+*/
+QmlBindableValue *QmlMetaProperty::binding()
+{
+ if(!isProperty() || type() & Attached)
+ return 0;
+
+ const QObjectList &children = object()->children();
+ for(QObjectList::ConstIterator iter = children.begin();
+ iter != children.end(); ++iter) {
+ QObject *child = *iter;
+ if(child->metaObject() == &QmlBindableValue::staticMetaObject) {
+ QmlBindableValue *v = static_cast<QmlBindableValue *>(child);
+ if(v->property() == *this)
+ return v;
+ }
+ }
+ return 0;
+}
+
+/*! \internal */
+int QmlMetaProperty::findSignal(const QObject *obj, const char *name)
+{
+ const QMetaObject *mo = obj->metaObject();
+ int methods = mo->methodCount();
+ for(int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ if(method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if(methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for(int ii = 0; ii < methods; ++ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QLatin1String(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if(methodName == name) {
+ signal = method;
+ coreIdx = ii;
+ return;
+ }
+ }
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if(attachedFunc == -1)
+ return 0;
+ else
+ return QmlMetaType::attachedPropertiesFuncById(attachedFunc)(object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if(type() & SignalProperty) {
+
+ const QObjectList &children = object()->children();
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if(sig && sig->index() == d->coreIdx)
+ return sig->expression();
+ }
+ } else if(type() & Property) {
+ if(type() & Attached)
+ return QVariant::fromValue(d->attachedObject());
+ else
+ return d->prop.read(object());
+ }
+ return QVariant();
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+/*!
+ Set the property value to \a value.
+*/
+void QmlMetaProperty::write(const QVariant &value) const
+{
+ if(type() & SignalProperty) {
+
+ QString expr = value.toString();
+ const QObjectList &children = object()->children();
+
+ for(int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ if(sig && sig->index() == d->coreIdx) {
+ if(expr.isEmpty()) {
+ sig->disconnect();
+ sig->deleteLater();
+ } else {
+ sig->setExpression(expr);
+ }
+ return;
+ }
+ }
+
+ if(!expr.isEmpty()) {
+ // XXX scope
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), expr, object(), d->coreIdx, object());
+ }
+
+ } else if(d->prop.name()) {
+
+ if(d->prop.isEnumType()) {
+ QVariant v = value;
+ if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ double integral;
+ double fractional = modf(value.toDouble(), &integral);
+ if (qFuzzyCompare(fractional, (double)0.0))
+ v.convert(QVariant::Int);
+ }
+ d->prop.write(object(), v);
+ } else {
+ if(!value.isValid())
+ return;
+
+ int t = propertyType();
+ int vt = value.type();
+
+ if(vt == t ||
+ value.userType() == t) {
+
+ void *a[1];
+ a[0] = (void *)value.constData();
+ QMetaObject::metacall(object(), QMetaObject::WriteProperty, d->coreIdx, a);
+
+ } else if(qMetaTypeId<QVariant>() == t) {
+
+ d->prop.write(object(), value);
+
+ } else if(propertyCategory() == Object) {
+
+ QObject *o = QmlMetaType::toQObject(value);
+ if(o)
+ d->prop.write(object(), QmlMetaType::fromObject(o, propertyType()));
+
+ } else if (propertyCategory() == List) {
+
+ int listType = QmlMetaType::listType(t);
+ if(value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = d->prop.read(object());
+ QmlMetaType::clear(listVar);
+ for(int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if(vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = d->prop.read(object());
+ if (!QmlMetaType::append(listVar, value)) {
+ qWarning() << "QmlMetaProperty: Unable to assign object to list";
+ }
+ }
+ } else if (propertyCategory() == QmlList) {
+ // XXX - optimize!
+ QVariant list = d->prop.read(object());
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if(objMo == mo)
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if(!found) {
+ qWarning() << "Unable to assign object to list";
+ return;
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else if(propertyCategory() == Normal) {
+
+ switch(t) {
+ case QVariant::Double:
+ {
+ qreal r;
+ bool found = true;
+ if(vt == QVariant::Int) {
+ r = value.toInt();
+ } else if(vt == QVariant::UInt) {
+ r = value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if(found) {
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ {
+ int i;
+ bool found = true;
+ if(vt == QVariant::Double) {
+ i = (int)value.toDouble();
+ } else if(vt == QVariant::UInt) {
+ i = (int)value.toUInt();
+ } else {
+ found = false;
+ }
+
+ if(found) {
+ void *a[1];
+ a[0] = &i;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+ case QVariant::String:
+ {
+ QString s;
+ bool found = true;
+ if(vt == QVariant::ByteArray) {
+ s = QLatin1String(value.toByteArray());
+ } else {
+ found = false;
+ }
+
+ if(found) {
+ void *a[1];
+ a[0] = &s;
+ QMetaObject::metacall(object(),
+ QMetaObject::WriteProperty,
+ d->coreIdx, a);
+ return;
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ d->prop.write(object(), value);
+ }
+
+ }
+ }
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if(type() & Property && !(type() & Attached)) {
+ return d->prop.hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Connect the property's change notifier signal to the \a dest \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if(!(type() & Property) || type() & Attached)
+ return false;
+
+ if(d->prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, d->prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connect the property's change notifier signal to the \a dest \a slot.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
+{
+ if(!(type() & Property) || type() & Attached)
+ return false;
+
+ if(d->prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + d->prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*! \internal */
+void QmlMetaProperty::emitSignal()
+{
+ if(type() & Signal) {
+ if(d->signal.parameterTypes().isEmpty())
+ d->object->metaObject()->activate(d->object, d->coreIdx, 0);
+ else
+ qWarning() << "QmlMetaProperty: Cannot emit signal with parameters";
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->coreIdx;
+}
+
+/*!
+ Returns the property information serialized into a single integer.
+ QmlMetaProperty uses the bottom 24 bits only.
+*/
+quint32 QmlMetaProperty::save() const
+{
+ quint32 rv = 0;
+ if(type() & Attached) {
+ rv = d->attachedFunc;
+ } else if(type() != Invalid) {
+ rv = d->coreIdx;
+ }
+
+ Q_ASSERT(rv <= 0xFFFF);
+ Q_ASSERT(type() <= 0xFF);
+ rv |= (type() << 16);
+
+ return rv;
+}
+
+/*!
+ Restore a QmlMetaProperty from a previously saved id. \a obj must be the
+ same object as used in the previous call to QmlMetaProperty::save(). Only
+ the bottom 24-bits are used, the high bits can be set to any value.
+*/
+void QmlMetaProperty::restore(quint32 id, QObject *obj)
+{
+ *this = QmlMetaProperty();
+ d->object = obj;
+
+ id &= 0xFFFFFF;
+ d->type = id >> 16;
+ id &= 0xFFFF;
+
+ if(d->type & Attached) {
+ d->attachedFunc = id;
+ } else if(d->type & Property) {
+ QMetaPropertyEx p(obj->metaObject()->property(id));
+ d->prop = p;
+ d->propType = p.propertyType;
+ d->coreIdx = id;
+ } else if(d->type & SignalProperty || d->type & Signal) {
+ d->signal = obj->metaObject()->method(id);
+ d->coreIdx = id;
+ }
+}
+
+/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ return d->signal;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
new file mode 100644
index 0000000..a2939f9
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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 QMLMETAPROPERTY_H
+#define QMLMETAPROPERTY_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlBindableValue;
+class QStringList;
+class QVariant;
+struct QMetaObject;
+class QmlContext;
+
+class QmlMetaPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlMetaProperty
+{
+public:
+ enum PropertyCategory {
+ Unknown,
+ InvalidProperty,
+ Bindable,
+ List,
+ QmlList, //XXX
+ Object,
+ Normal
+ };
+ QmlMetaProperty();
+ QmlMetaProperty(QObject *, QmlContext * = 0);
+ QmlMetaProperty(QObject *, const QString &, QmlContext * = 0);
+ QmlMetaProperty(const QmlMetaProperty &);
+ QmlMetaProperty &operator=(const QmlMetaProperty &);
+ QmlMetaProperty(QObject *, int, PropertyCategory = Unknown, QmlContext * = 0);
+ ~QmlMetaProperty();
+
+ static QStringList properties(QObject *);
+ QString name() const;
+
+ QVariant read() const;
+ void write(const QVariant &) const;
+ void emitSignal();
+
+ bool hasChangedNotifier() const;
+ bool connectNotifier(QObject *dest, const char *slot) const;
+ bool connectNotifier(QObject *dest, int method) const;
+
+ quint32 save() const;
+ void restore(quint32, QObject *);
+
+ QMetaMethod method() const;
+
+ enum Type { Invalid = 0x00,
+ Property = 0x01,
+ SignalProperty = 0x02,
+ Signal = 0x04,
+ Default = 0x08,
+ Attached = 0x10 };
+
+ Type type() const;
+ bool isProperty() const;
+ bool isDefault() const;
+ bool isWritable() const;
+ bool isDesignable() const;
+ bool isValid() const;
+ QObject *object() const;
+
+ PropertyCategory propertyCategory() const;
+ static PropertyCategory propertyCategory(const QMetaProperty &);
+
+ int propertyType() const;
+ const char *propertyTypeName() const;
+
+ bool operator==(const QmlMetaProperty &) const;
+
+ const QMetaProperty &property() const;
+
+ QmlBindableValue *binding();
+ static int findSignal(const QObject *, const char *);
+
+ int coreIndex() const;
+private:
+ friend class QmlEnginePrivate;
+ QmlMetaPropertyPrivate *d;
+};
+typedef QList<QmlMetaProperty> QmlMetaProperties;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETAPROPERTY_H
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
new file mode 100644
index 0000000..5c13f5e
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 QMLMETAPROPERTY_P_H
+#define QMLMETAPROPERTY_P_H
+
+class QmlContext;
+class QmlMetaPropertyPrivate
+{
+public:
+ QmlMetaPropertyPrivate()
+ : context(0), coreIdx(-1), type(QmlMetaProperty::Invalid), attachedFunc(-1),
+ object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
+ : name(other.name), signal(other.signal), context(other.context),
+ coreIdx(other.coreIdx), type(other.type), attachedFunc(other.attachedFunc),
+ object(other.object), prop(other.prop), propType(other.propType),
+ category(other.category) {}
+
+ QString name;
+ QMetaMethod signal;
+ QmlContext *context;
+ int coreIdx;
+ uint type;
+ int attachedFunc;
+ QObject *object;
+ QMetaProperty prop;
+ int propType;
+
+ mutable QmlMetaProperty::PropertyCategory category;
+
+ QObject *attachedObject() const;
+ void findSignalInt(QObject *, const QString &);
+};
+
+#endif // QMLMETAPROPERTY_P_H
+
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
new file mode 100644
index 0000000..584ccde
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -0,0 +1,1164 @@
+/****************************************************************************
+**
+** 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 "qmlmetatype.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qbitarray.h>
+#include <QtCore/qreadwritelock.h>
+#include <private/qmlproxymetaobject_p.h>
+
+#include <qmetatype.h>
+#include <qobjectdefs.h>
+#include <qdatetime.h>
+#include <qbytearray.h>
+#include <qreadwritelock.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvector.h>
+#include <qlocale.h>
+#include <QtCore/qcryptographichash.h>
+#include <qmlcustomparser.h>
+
+QT_BEGIN_NAMESPACE
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include <qbitarray.h>
+# include <qurl.h>
+# include <qvariant.h>
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include <qsize.h>
+# include <qpoint.h>
+# include <qrect.h>
+# include <qline.h>
+#endif
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+struct QmlMetaTypeData
+{
+ QList<QmlType *> types;
+ typedef QHash<int, QmlType *> Ids;
+ Ids idToType;
+ typedef QHash<QByteArray, QmlType *> Names;
+ Names nameToType;
+ typedef QHash<const QMetaObject *, QmlType *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<QByteArray, QmlCustomParser *> CustomParsers;
+ CustomParsers customParsers;
+ typedef QHash<int, QmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray qmllists;
+ QBitArray lists;
+};
+Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData);
+Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock);
+
+class QmlTypePrivate
+{
+public:
+ QmlTypePrivate();
+
+ void init() const;
+
+ bool m_isInterface : 1;
+ const char *m_iid;
+ QByteArray m_name;
+ int m_typeId; int m_listId; int m_qmlListId;
+ QmlPrivate::Func m_opFunc;
+ const QMetaObject *m_baseMetaObject;
+ QmlAttachedPropertiesFunc m_attachedPropertiesFunc;
+ int m_parserStatusCast;
+ QmlPrivate::CreateFunc m_extFunc;
+ const QMetaObject *m_extMetaObject;
+ int m_index;
+ mutable volatile bool m_isSetup:1;
+ mutable QList<QmlProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QByteArray m_hash;
+};
+
+QmlTypePrivate::QmlTypePrivate()
+: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
+ m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
+ m_parserStatusCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_isSetup(false)
+{
+}
+
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *iid, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_isInterface = true;
+ d->m_iid = iid;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_index = index;
+ d->m_isSetup = true;
+}
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *qmlName,
+ const QMetaObject *metaObject,
+ QmlAttachedPropertiesFunc attachedPropertiesFunc,
+ int parserStatusCast, QmlPrivate::CreateFunc extFunc,
+ const QMetaObject *extMetaObject, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_name = qmlName;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_baseMetaObject = metaObject;
+ d->m_attachedPropertiesFunc = attachedPropertiesFunc;
+ d->m_parserStatusCast = parserStatusCast;
+ d->m_extFunc = extFunc;
+ d->m_index = index;
+
+ if(extMetaObject)
+ d->m_extMetaObject = extMetaObject;
+}
+
+QmlType::~QmlType()
+{
+ delete d;
+}
+
+void QmlTypePrivate::init() const
+{
+ if(m_isSetup) return;
+
+ QWriteLocker lock(metaTypeDataLock());
+ if(m_isSetup)
+ return;
+
+ // Setup extended meta object
+ // XXX - very inefficient
+ const QMetaObject *mo = m_baseMetaObject;
+ if(m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *m_extMetaObject;
+ mmo->d.superdata = mo;
+ QmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+
+ mo = mo->d.superdata;
+ while(mo) {
+ QmlType *t = metaTypeData()->metaObjectToType.value(mo);
+ if(t) {
+ if(t->d->m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *t->d->m_extMetaObject;
+ mmo->d.superdata = m_baseMetaObject;
+ if(!m_metaObjects.isEmpty())
+ m_metaObjects.last().metaObject->d.superdata = mmo;
+ QmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0 };
+ m_metaObjects << data;
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ for(int ii = 0; ii < m_metaObjects.count(); ++ii)
+ m_metaObjects[ii].propertyOffset =
+ m_metaObjects.at(ii).metaObject->propertyOffset();
+
+ // Calculate hash
+ QByteArray hashData;
+
+ const QMetaObject *myMetaObject = m_metaObjects.isEmpty()?m_baseMetaObject:m_metaObjects.first().metaObject;
+
+ for(int ii = 0; ii < myMetaObject->propertyCount(); ++ii) {
+ QMetaProperty prop = myMetaObject->property(ii);
+ hashData.append(prop.type());
+ hashData.append("|");
+ hashData.append(prop.name());
+ hashData.append("|");
+ }
+
+ for(int ii = 0; ii < myMetaObject->methodCount(); ++ii) {
+ QMetaMethod method = myMetaObject->method(ii);
+ hashData.append(method.signature());
+ hashData.append("|");
+ }
+
+ m_hash = QCryptographicHash::hash(hashData, QCryptographicHash::Md5);
+
+ m_isSetup = true;
+ lock.unlock();
+}
+
+QByteArray QmlType::typeName() const
+{
+ if(d->m_baseMetaObject)
+ return d->m_baseMetaObject->className();
+ else
+ return QByteArray();
+}
+
+QByteArray QmlType::qmlTypeName() const
+{
+ return d->m_name;
+}
+
+QByteArray QmlType::hash() const
+{
+ d->init();
+
+ return d->m_hash;
+}
+
+QObject *QmlType::create() const
+{
+ d->init();
+
+ QVariant v;
+ QObject *rv = 0;
+ d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv);
+
+ if (rv && !d->m_metaObjects.isEmpty())
+ (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects);
+
+ return rv;
+}
+
+bool QmlType::isInterface() const
+{
+ return d->m_isInterface;
+}
+
+int QmlType::typeId() const
+{
+ return d->m_typeId;
+}
+
+int QmlType::qListTypeId() const
+{
+ return d->m_listId;
+}
+
+int QmlType::qmlListTypeId() const
+{
+ return d->m_qmlListId;
+}
+
+void QmlType::listClear(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant arg;
+ d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0);
+}
+
+void QmlType::listAppend(const QVariant &list, const QVariant &item)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ d->m_opFunc(QmlPrivate::Append, 0, list, item, 0);
+}
+
+QVariant QmlType::listAt(const QVariant &list, int idx)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant rv;
+ void *ptr = (void *)&rv;
+ d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr);
+ return rv;
+}
+
+int QmlType::listCount(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0);
+}
+
+const QMetaObject *QmlType::metaObject() const
+{
+ d->init();
+
+ if(d->m_metaObjects.isEmpty())
+ return d->m_baseMetaObject;
+ else
+ return d->m_metaObjects.first().metaObject;
+
+}
+
+const QMetaObject *QmlType::baseMetaObject() const
+{
+ return d->m_baseMetaObject;
+}
+
+QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const
+{
+ return d->m_attachedPropertiesFunc;
+}
+
+int QmlType::parserStatusCast() const
+{
+ return d->m_parserStatusCast;
+}
+
+QVariant QmlType::fromObject(QObject *obj) const
+{
+ QVariant rv;
+ QVariant *v_ptr = &rv;
+ QVariant vobj = QVariant::fromValue(obj);
+ d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr);
+ return rv;
+}
+
+const char *QmlType::interfaceIId() const
+{
+ return d->m_iid;
+}
+
+int QmlType::index() const
+{
+ return d->m_index;
+}
+
+int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
+ QmlPrivate::Func listFunction,
+ const char *iid)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ listFunction, iid, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ if(data->interfaces.size() < id.typeId)
+ data->interfaces.resize(id.typeId + 16);
+ if(data->qmllists.size() < id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if(data->lists.size() < id.listId)
+ data->lists.resize(id.listId + 16);
+ data->interfaces.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo)
+{
+ Q_UNUSED(object);
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QString name = QLatin1String(cname);
+ for(int ii = 0; ii < name.count(); ++ii) {
+ if(!name.at(ii).isLetterOrNumber()) {
+ qWarning("QmlMetaType: Invalid QML name %s", cname);
+ return -1;
+ }
+ }
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ func, cname, mo, attach, pStatus, extFunc,
+ extmo, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+
+ if(!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ data->metaObjectToType.insert(type->baseMetaObject(), type);
+
+ if(data->objects.size() <= id.typeId)
+ data->objects.resize(id.typeId + 16);
+ if(data->qmllists.size() <= id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if(data->lists.size() <= id.listId)
+ data->lists.resize(id.listId + 16);
+ data->objects.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+void QmlMetaType::registerCustomParser(const char *qmlName,
+ QmlCustomParser *parser)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ Q_ASSERT(parser);
+ if(data->customParsers.contains(qmlName)) {
+ delete parser;
+ return;
+ }
+
+ data->customParsers.insert(qmlName, parser);
+}
+
+QmlCustomParser *QmlMetaType::customParser(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->customParsers.value(name);
+}
+
+
+int QmlMetaType::qmlParserStatusCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if(type && type->typeId() == userType)
+ return type->parserStatusCast();
+ else
+ return -1;
+}
+
+QObject *QmlMetaType::toQObject(const QVariant &v)
+{
+ if(!isObject(v.userType()))
+ return 0;
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *rv = *(QObject **)v.constData();
+ return rv;
+}
+
+/*
+ Returns the item type for a list of type \a id.
+ */
+int QmlMetaType::listType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if(type && type->qListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+/*
+ Returns the item type for a qml list of type \a id.
+ */
+int QmlMetaType::qmlListType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if(type && type->qmlListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::clear(const QVariant &list)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if(type && type->qListTypeId() == userType) {
+ type->listClear(list);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaType::append(const QVariant &list, const QVariant &item)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if(type && type->qListTypeId() == userType &&
+ item.userType() == type->typeId()) {
+ type->listAppend(list, item);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QObject *QmlMetaType::create(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ lock.unlock();
+
+ QmlType *type = data->nameToType.value(name);
+ if(type)
+ return type->create();
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::fromObject(QObject *obj, int typeId)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(typeId);
+ if(type && type->typeId() == typeId)
+ return type->fromObject(obj);
+ else
+ return QVariant();
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(id);
+ if(type && type->typeId() == id)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if(type)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ lock.unlock();
+
+ if(type && type->typeId() == id)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ lock.unlock();
+
+ if(type)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+int QmlMetaType::type(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if(type)
+ return type->typeId();
+ else
+ return 0;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->nameToType.value(name);
+ if(type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id)
+{
+ if(id < 0)
+ return 0;
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return data->types.at(id)->attachedPropertiesFunction();
+}
+
+QmlAttachedPropertiesFunc
+QmlMetaType::attachedPropertiesFunc(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->nameToType.value(name);
+ if(type)
+ return type->attachedPropertiesFunction();
+ else
+ return 0;
+}
+
+QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultProperty");
+ while(idx == -1 && metaObject) {
+ metaObject = metaObject->superClass();
+ if(metaObject)
+ idx = metaObject->indexOfClassInfo("DefaultProperty");
+ }
+ if(-1 == idx)
+ return QMetaProperty();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if(!info.value())
+ return QMetaProperty();
+
+ idx = metaObject->indexOfProperty(info.value());
+ if(-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QMetaProperty QmlMetaType::defaultProperty(QObject *obj)
+{
+ if(!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultProperty(metaObject);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultMethod");
+ while(idx == -1 && metaObject) {
+ metaObject = metaObject->superClass();
+ if(metaObject)
+ idx = metaObject->indexOfClassInfo("DefaultMethod");
+ }
+ if(-1 == idx)
+ return QMetaMethod();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if(!info.value())
+ return QMetaMethod();
+
+ idx = metaObject->indexOfMethod(info.value());
+ if(-1 == idx)
+ return QMetaMethod();
+
+ return metaObject->method(idx);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(QObject *obj)
+{
+ if(!obj)
+ return QMetaMethod();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultMethod(metaObject);
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const QByteArray &bname)
+{
+ return property(obj, bname.constData());
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const char *name)
+{
+ if(!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int idx = metaObject->indexOfProperty(name);
+ if(-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+bool QmlMetaType::isObject(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+}
+
+bool QmlMetaType::isInterface(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+}
+
+const char *QmlMetaType::interfaceIId(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if(type && type->isInterface() && type->typeId() == userType)
+ return type->interfaceIId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::isObject(const QMetaObject *mo)
+{
+ while(mo) {
+ if(mo == &QObject::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+bool QmlMetaType::isQmlList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType);
+}
+
+bool QmlMetaType::isList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+}
+
+bool QmlMetaType::isList(const QVariant &v)
+{
+ return (v.type() == QVariant::UserType && isList(v.userType()));
+}
+
+int QmlMetaType::listCount(const QVariant &v)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if(type && type->qListTypeId() == userType)
+ return type->listCount(v);
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::listAt(const QVariant &v, int idx)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if(type && type->qListTypeId() == userType)
+ return type->listAt(v, idx);
+ else
+ return 0;
+}
+
+/*!
+ A custom string convertor allows you to specify a function pointer that
+ returns a variant of \a type. For example, if you have written your own icon
+ class that you want to support as an object property assignable in QML:
+
+ \code
+ int type = qRegisterMetaType<SuperIcon>("SuperIcon");
+ QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
+ \endcode
+
+ The function pointer must be of the form:
+ \code
+ QVariant (*StringConverter)(const QString &);
+ \endcode
+ */
+void QmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
+{
+ QWriteLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ if(data->stringConverters.contains(type))
+ return;
+ data->stringConverters.insert(type, converter);
+}
+
+/*!
+ Return the custom string converter for \a type, previously installed through
+ registerCustomStringConverter()
+ */
+QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ return data->stringConverters.value(type);
+}
+
+QmlType *QmlMetaType::qmlType(const QByteArray &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.value(name);
+}
+
+QList<QByteArray> QmlMetaType::qmlTypeNames()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.keys();
+}
+
+/*!
+ 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
+ successful and false if not.
+
+ \note This should move into QMetaType once complete
+
+*/
+bool QmlMetaType::copy(int type, void *data, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = *static_cast<const long*>(copy);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = *static_cast<const int*>(copy);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = *static_cast<const short*>(copy);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = *static_cast<const char*>(copy);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = *static_cast<const float*>(copy);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = *static_cast<const double*>(copy);
+ return true;
+ 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;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
+ return true;
+ 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;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
+ return true;
+ 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;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
+ return true;
+ 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;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = 0;
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = long(0);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = int(0);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = short(0);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = char(0);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = ulong(0);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = uint(0);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = qlonglong(0);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = qulonglong(0);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = ushort(0);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = uchar(0);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = bool(false);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = float(0);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = double();
+ return true;
+ 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;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
+ return true;
+ 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;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = NS(QString)();
+ return true;
+ 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;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = NS(QTime)();
+ return true;
+ 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;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = NS(QSize)();
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = NS(QLine)();
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
+ return true;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
+ return true;
+#endif
+ case QMetaType::Void:
+ return true;
+ default:
+ ;
+ }
+ }
+
+ return false;
+}
+
+void qmlRegisterCustomParser(const char *qmlName, QmlCustomParser *parser)
+{
+ QmlMetaType::registerCustomParser(qmlName, parser);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
new file mode 100644
index 0000000..3daa14b
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** 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 QMLMETATYPE_H
+#define QMLMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qbitarray.h>
+#include <QtDeclarative/qmlprivate.h>
+#include <QtDeclarative/qmlparserstatus.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlType;
+class QmlCustomParser;
+class Q_DECLARATIVE_EXPORT QmlMetaType
+{
+public:
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo);
+ static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
+ static void registerCustomParser(const char *, QmlCustomParser *);
+
+ static QmlCustomParser *customParser(const QByteArray &);
+
+ static bool copy(int type, void *data, const void *copy = 0);
+
+ static QmlType *qmlType(const QByteArray &);
+ static QList<QByteArray> qmlTypeNames();
+
+ static QMetaProperty defaultProperty(const QMetaObject *);
+ static QMetaProperty defaultProperty(QObject *);
+ static QMetaMethod defaultMethod(const QMetaObject *);
+ static QMetaMethod defaultMethod(QObject *);
+ static QMetaProperty property(QObject *, const QByteArray &);
+ static QMetaProperty property(QObject *, const char *);
+ static QObject *toQObject(const QVariant &);
+ static int qmlParserStatusCast(int);
+ static int listType(int);
+ static int type(const QByteArray &);
+ static int type(const QString &);
+ static bool clear(const QVariant &);
+ static bool append(const QVariant &, const QVariant &);
+ static QVariant fromObject(QObject *, int type);
+ static QObject *create(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(const QByteArray &);
+ static const QMetaObject *rawMetaObjectForType(int);
+ static const QMetaObject *metaObjectForType(const QByteArray &);
+ static const QMetaObject *metaObjectForType(int);
+ static int attachedPropertiesFuncId(const QByteArray &);
+ static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+ static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &);
+
+ static bool isInterface(int);
+ static const char *interfaceIId(int);
+ static bool isObject(int);
+ static bool isObject(const QMetaObject *);
+ static bool isList(int);
+ static bool isList(const QVariant &);
+ static bool isQmlList(int);
+ static int qmlListType(int);
+ static int listCount(const QVariant &);
+ static QVariant listAt(const QVariant &, int);
+
+ typedef QVariant (*StringConverter)(const QString &);
+ static void registerCustomStringConverter(int, StringConverter);
+ static StringConverter customStringConverter(int);
+};
+
+class QmlTypePrivate;
+class QmlType
+{
+public:
+ QByteArray typeName() const;
+ QByteArray qmlTypeName() const;
+
+ QByteArray hash() const;
+
+ QObject *create() const;
+
+ bool isInterface() const;
+ int typeId() const;
+ int qListTypeId() const;
+ int qmlListTypeId() const;
+
+ void listClear(const QVariant &);
+ void listAppend(const QVariant &, const QVariant &);
+ QVariant listAt(const QVariant &, int);
+ int listCount(const QVariant &);
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+
+ QmlAttachedPropertiesFunc attachedPropertiesFunction() const;
+
+ int parserStatusCast() const;
+ QVariant fromObject(QObject *) const;
+ const char *interfaceIId() const;
+
+ int index() const;
+private:
+ friend class QmlMetaType;
+ friend class QmlTypePrivate;
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int, QmlPrivate::CreateFunc, const QMetaObject *, int);
+ ~QmlType();
+
+ QmlTypePrivate *d;
+};
+
+template<typename T>
+int qmlRegisterType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0);
+}
+
+template<typename T>
+int qmlRegisterType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ 0, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ if(!attached)
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0,
+ &T::staticMetaObject, attached,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ if(!attached)
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ qmlName,
+ &T::staticMetaObject,
+ attached,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ &QmlPrivate::CreateParent<E>::create,
+ &E::staticMetaObject);
+}
+
+template<typename T>
+int qmlRegisterInterface(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerInterface(ids,
+ QmlPrivate::list_interface_op<T>,
+ qobject_interface_iid<T *>());
+}
+
+void qmlRegisterCustomParser(const char *qmlName, QmlCustomParser *);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETATYPE_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
new file mode 100644
index 0000000..54db32e
--- /dev/null
+++ b/src/declarative/qml/qmlparser.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** 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 "qmlparser_p.h"
+#include <QStack>
+#include <qmlpropertyvaluesource.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlvme_p.h>
+#include <qmlbindablevalue.h>
+#include <qfxperf.h>
+#include <qml.h>
+#include "private/qmlcomponent_p.h"
+#include <qmlcomponent.h>
+#include <qmlbasicscript.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <private/qmlvmemetaobject_p.h>
+#include "private/qmlxmlparser_p.h"
+#include <private/qmlcompiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+QmlParser::Object::Object()
+: type(-1), metatype(0), extObject(0), defaultProperty(0), line(-1),
+ dynamicPropertiesProperty(0), dynamicSignalsProperty(0)
+{
+}
+
+QmlParser::Object::~Object()
+{
+ if(defaultProperty) defaultProperty->release();
+ foreach(Property *prop, properties)
+ prop->release();
+ if(dynamicPropertiesProperty) dynamicPropertiesProperty->release();
+ if(dynamicSignalsProperty) dynamicSignalsProperty->release();
+}
+
+const QMetaObject *Object::metaObject() const
+{
+ if(extObject && metatype)
+ return extObject;
+ else
+ return metatype;
+}
+
+QmlParser::Property *Object::getDefaultProperty()
+{
+ if(!defaultProperty)
+ defaultProperty = new Property;
+ return defaultProperty;
+}
+
+Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
+{
+ if(!properties.contains(name)) {
+ if(create)
+ properties.insert(name, new Property(name));
+ else
+ return 0;
+ }
+ return properties[name];
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), type(Variant), defaultValue(0)
+{
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
+: isDefaultProperty(o.isDefaultProperty),
+ type(o.type),
+ name(o.name),
+ onValueChanged(o.onValueChanged),
+ defaultValue(o.defaultValue)
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal()
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
+: name(o.name)
+{
+}
+
+QmlParser::Property::Property()
+: type(0), index(-1), value(0), isDefault(true), line(-1)
+{
+}
+
+QmlParser::Property::Property(const QByteArray &n)
+: type(0), index(-1), value(0), name(n), isDefault(false), line(-1)
+{
+}
+
+QmlParser::Property::~Property()
+{
+ foreach(Value *value, values)
+ value->release();
+ if(value) value->release();
+}
+
+Object *QmlParser::Property::getValue()
+{
+ if(!value) value = new Object;
+ return value;
+}
+
+void QmlParser::Property::addValue(Value *v)
+{
+ values << v;
+}
+
+QmlParser::Value::Value()
+: type(Unknown), object(0), line(-1)
+{
+}
+
+QmlParser::Value::~Value()
+{
+ if(object) object->release();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
new file mode 100644
index 0000000..9d3f3f6
--- /dev/null
+++ b/src/declarative/qml/qmlparser_p.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** 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 QMLPARSER_P_H
+#define QMLPARSER_P_H
+
+#include <QByteArray>
+#include <QList>
+#include <qml.h>
+#include "qmlcomponent_p.h"
+#include <private/qmlrefcount_p.h>
+#include "qmlcompiledcomponent_p.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlXmlParser;
+
+/*
+ XXX
+
+ These types are created (and owned) by the QmlXmlParser and consumed by the
+ QmlCompiler. During the compilation phase the compiler will update some of
+ the fields for both its own use and for the use of the upcoming QmlDom API.
+
+ The types are part of the generic sounding "QmlParser" namespace for legacy
+ reasons (there used to be more in this namespace) and will be cleaned up and
+ migrated into a more appropriate location shortly.
+*/
+namespace QmlParser
+{
+ class Property;
+ class Object : public QmlRefCount
+ {
+ public:
+ Object();
+ virtual ~Object();
+
+ // Type of the object. The integer is an index into the
+ // QmlCompiledData::types array, or -1 if the object is a fetched
+ // object.
+ int type;
+ // The name of this type
+ QByteArray typeName;
+ // The id assigned to the object (if any).
+ QByteArray id;
+ // Custom parsed data
+ QByteArray custom;
+ // Returns the metaobject for this type, or 0 if not available.
+ // Internally selectd between the metatype and extObject variables
+ const QMetaObject *metaObject() const;
+
+ // The compile time metaobject for this type
+ const QMetaObject *metatype;
+ // The synthesized metaobject, if QML added signals or properties to
+ // this type. Otherwise null
+ QMetaObject *extObject;
+
+ Property *getDefaultProperty();
+ Property *getProperty(const QByteArray &name, bool create=true);
+
+ Property *defaultProperty;
+ QHash<QByteArray, Property *> properties;
+
+ qint64 line;
+
+ struct DynamicProperty {
+ DynamicProperty();
+ DynamicProperty(const DynamicProperty &);
+
+ enum Type { Variant, Int, Bool, Real, String, Color, Date };
+
+ bool isDefaultProperty;
+ Type type;
+ QByteArray name;
+ QString onValueChanged;
+ QmlParser::Property *defaultValue;
+ };
+ struct DynamicSignal {
+ DynamicSignal();
+ DynamicSignal(const DynamicSignal &);
+
+ QByteArray name;
+ };
+
+ // The "properties" property
+ Property *dynamicPropertiesProperty;
+ // The "signals" property
+ Property *dynamicSignalsProperty;
+ // The list of dynamic properties described in the "properties" property
+ QList<DynamicProperty> dynamicProperties;
+ // The list of dynamic signals described in the "signals" property
+ QList<DynamicSignal> dynamicSignals;
+ };
+
+ class Value : public QmlRefCount
+ {
+ public:
+ Value();
+ virtual ~Value();
+
+ enum Type {
+ // The type of this value assignment is not yet known
+ Unknown,
+ // This is used as a literal property assignment
+ Literal,
+ // This is used as a property binding assignment
+ PropertyBinding,
+ // This is used as a QmlPropertyValueSource assignment
+ ValueSource,
+ // This is used as a property QObject assignment
+ CreatedObject,
+ // This is used as a signal object assignment
+ SignalObject,
+ // This is used as a signal expression assignment
+ SignalExpression,
+ // This is used as an implicit component creation
+ Component,
+ // This is used as an id assignment only
+ Id
+ };
+ Type type;
+
+ // Primitive value
+ QString primitive;
+ // Object value
+ Object *object;
+
+ qint64 line;
+ };
+
+ class Property : public QmlRefCount
+ {
+ public:
+ Property();
+ Property(const QByteArray &n);
+ virtual ~Property();
+
+ Object *getValue();
+ void addValue(Value *v);
+
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // unknown.
+ int type;
+ // The metaobject index of this property, or -1 if unknown.
+ int index;
+
+ // The list of values assigned to this property. Content in values
+ // and value are mutually exclusive
+ QList<Value *> values;
+ // The accessed property. This is used to represent dot properties.
+ // Content in value and values are mutually exclusive.
+ Object *value;
+ // The property name
+ QByteArray name;
+ // True if this property was accessed as the default property.
+ bool isDefault;
+
+ qint64 line;
+ };
+}
+
+#endif // QMLPARSER_P_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
new file mode 100644
index 0000000..3bb421d
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 "qmlparserstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlParserStatus
+ \brief provides updates on the parser state.
+*/
+
+/*!
+ Invoked after class creation, but before any properties have been set.
+*/
+void QmlParserStatus::classBegin()
+{
+}
+
+/*!
+ Invoked after all properties have been set to their static values. At this
+ point bindings are still to be evaluated.
+*/
+void QmlParserStatus::classComplete()
+{
+}
+
+/*!
+ Invoked after the root component that caused this instantiation has
+ completed construction. At this point all static values and binding values
+ have been assigned to the class.
+*/
+void QmlParserStatus::componentComplete()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
new file mode 100644
index 0000000..1ec50ba
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QMLPARSERSTATUS_H
+#define QMLPARSERSTATUS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlParserStatus
+{
+public:
+ virtual ~QmlParserStatus() {}
+
+ virtual void classBegin();
+ virtual void classComplete();
+ virtual void componentComplete();
+};
+Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus");
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSERSTATUS_H
diff --git a/src/declarative/qml/qmlprivate.cpp b/src/declarative/qml/qmlprivate.cpp
new file mode 100644
index 0000000..21b19e8
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 "qmlprivate.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlPrivate::InstanceType::InstanceType(int) {}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h
new file mode 100644
index 0000000..183f42b
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.h
@@ -0,0 +1,365 @@
+/****************************************************************************
+**
+** 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 QMLPRIVATE_H
+#define QMLPRIVATE_H
+
+#include <QtCore/qglobal.h>
+#ifndef Q_OS_WIN32
+#include <stdint.h>
+#endif
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+typedef QObject *(*QmlAttachedPropertiesFunc)(QObject *);
+
+namespace QmlPrivate
+{
+ class ListInterface
+ {
+ public:
+ virtual ~ListInterface() {}
+ virtual int type() const = 0;
+ virtual void append(void *) = 0;
+ virtual void insert(int, void *) = 0;
+ virtual void removeAt(int) = 0;
+ virtual void at(int, void *) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ };
+
+ enum ListOp { Append, Set, Insert, Prepend, Length, FromObject,
+ Object, Create, Value, Clear };
+
+ template<typename T>
+ int list_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_nocreate_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_interface_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<class From, class To, int N>
+ struct StaticCastSelectorClass
+ {
+ static inline int cast() { return -1; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelectorClass<From, To, sizeof(int)>
+ {
+#ifndef Q_OS_SYMBIAN
+ static inline int cast() { return (int)((intptr_t)static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#else
+ static inline int cast() { return (int)(static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+#endif
+ };
+
+ template<class From, class To>
+ struct StaticCastSelector
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ static yes_type check(To *);
+ static no_type check(...);
+
+ static inline int cast()
+ {
+ return StaticCastSelectorClass<From, To, sizeof(check((From *)0))>::cast();
+ }
+ };
+
+ template<typename T, int N>
+ struct AttachedPropertySelector
+ {
+ static inline QmlAttachedPropertiesFunc func()
+ {
+ return 0;
+ }
+ };
+ template<typename T>
+ struct AttachedPropertySelector<T, 1>
+ {
+ static inline QmlAttachedPropertiesFunc func()
+ {
+ return &T::qmlAttachedProperties;
+ }
+ };
+
+ template < typename T >
+ class has_attachedProperties {
+ typedef int yes_type;
+ typedef char no_type;
+
+ template<typename S, QObject *(S::*)(QObject *)>
+ struct dummy {};
+
+ template<typename S, QObject *(S::*)(QObject *) const>
+ struct dummy_const {};
+
+ template<typename S, QObject *(*) (QObject *)>
+ struct dummy_static {};
+
+ template<typename S>
+ static no_type check(dummy<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static no_type check(dummy_const<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static yes_type check(dummy_static<S, &S::qmlAttachedProperties> *);
+
+ template<typename S>
+ static no_type check(...);
+
+ public:
+ static bool const value = sizeof(check<T>(0)) == sizeof(yes_type);
+ };
+
+ template<typename T>
+ inline QmlAttachedPropertiesFunc attachedPropertiesFunc()
+ {
+ return AttachedPropertySelector<T, has_attachedProperties<T>::value>::func();
+ }
+
+ struct MetaTypeIds {
+ int typeId;
+ int listId;
+ int qmlListId;
+ };
+ typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **);
+ typedef QObject *(*CreateFunc)(QObject *);
+
+ template<typename T>
+ struct CreateParent {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+
+ template<typename T>
+ struct CreateNoParent {
+ static QObject *create() {
+ return new T;
+ }
+ };
+
+ struct Q_DECLARATIVE_EXPORT InstanceType {
+ InstanceType(int);
+ };
+
+ template<typename T>
+ struct Define {
+ static InstanceType instance;
+ };
+
+ template<typename T>
+ struct ExtCreate {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+};
+
+template<typename T>
+int QmlPrivate::list_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ if(op == QmlPrivate::Create) {
+ QObject *obj = static_cast<QObject *>(new T);
+ *((QObject **)out) = obj;
+ return 0;
+ }
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if(me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if(me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ break;
+ case QmlPrivate::FromObject:
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+
+#endif // QMLPRIVATE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp
new file mode 100644
index 0000000..78b0495
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 "qmlpropertyvaluesource.h"
+#include "qml.h"
+
+
+QT_BEGIN_NAMESPACE
+/*!
+ \class QmlPropertyValueSource
+ \brief The QmlPropertyValueSource class is inherited by property value sources such as animations and bindings.
+ */
+QML_DEFINE_NOCREATE_TYPE(QmlPropertyValueSource);
+
+QmlPropertyValueSource::QmlPropertyValueSource(QObject *parent)
+ : QObject(parent)
+
+{
+}
+
+QmlPropertyValueSource::QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Set the target \a property for the value source. This method will be called
+ by the QML engine when assigning a value source.
+
+ The default implementation does nothing.
+*/
+void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property)
+{
+ Q_UNUSED(property);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h
new file mode 100644
index 0000000..6ef2e38
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QMLPROPERTYVALUESOURCE_H
+#define QMLPROPERTYVALUESOURCE_H
+
+#include <qfxglobal.h>
+#include <qml.h>
+#include <QObject>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QObjectPrivate;
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueSource : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ QmlPropertyValueSource(QObject *parent);
+ virtual void setTarget(const QmlMetaProperty &);
+
+protected:
+ QmlPropertyValueSource(QObjectPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QmlPropertyValueSource)
+};
+QML_DECLARE_TYPE(QmlPropertyValueSource);
+
+#endif // QMLPROPERTYVALUESOURCE_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp
new file mode 100644
index 0000000..3b9f6ca
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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 "qmlproxymetaobject_p.h"
+
+
+QT_BEGIN_NAMESPACE
+QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
+: metaObjects(mList), proxies(0), parent(0), object(obj)
+{
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className();
+#endif
+
+ *static_cast<QMetaObject *>(this) = *metaObjects->last().metaObject;
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if(op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ op->metaObject = this;
+
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ const QMetaObject *mo = obj->metaObject();
+ while(mo) {
+ qWarning() << " " << mo->className();
+ mo = mo->superClass();
+ }
+#endif
+}
+
+QmlProxyMetaObject::~QmlProxyMetaObject()
+{
+ if(parent)
+ delete parent;
+ parent = 0;
+
+ if(proxies)
+ delete [] proxies;
+ proxies = 0;
+}
+
+int QmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if((c == QMetaObject::ReadProperty ||
+ c == QMetaObject::WriteProperty) &&
+ id >= metaObjects->last().propertyOffset) {
+
+ for(int ii = 0; ii < metaObjects->count(); ++ii) {
+ const ProxyData &data = metaObjects->at(ii);
+ if(id >= data.propertyOffset) {
+ if(!proxies) {
+ proxies = new QObject*[metaObjects->count()];
+ ::memset(proxies, 0,
+ sizeof(QObject *) * metaObjects->count());
+ }
+
+ if(!proxies[ii])
+ proxies[ii] = data.createFunc(object);
+
+ int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
+ int proxyId = id - data.propertyOffset + proxyOffset;
+
+ return proxies[ii]->qt_metacall(c, proxyId, a);
+ }
+ }
+ }
+
+ if(parent)
+ return parent->metaCall(c, id, a);
+ else
+ return object->qt_metacall(c, id, a);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h
new file mode 100644
index 0000000..594e7a3
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QMLPROXYMETAOBJECT_P_H
+#define QMLPROXYMETAOBJECT_P_H
+
+#include <QMetaObject>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qobject_p.h>
+#include <QObject>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlProxyMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ struct ProxyData {
+ typedef QObject *(*CreateFunc)(QObject *);
+ QMetaObject *metaObject;
+ CreateFunc createFunc;
+ int propertyOffset;
+ };
+
+ QmlProxyMetaObject(QObject *, QList<ProxyData> *);
+ virtual ~QmlProxyMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QList<ProxyData> *metaObjects;
+ QObject **proxies;
+
+ QAbstractDynamicMetaObject *parent;
+ QObject *object;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROXYMETAOBJECT_P_H
+
diff --git a/src/declarative/qml/qmlrefcount.cpp b/src/declarative/qml/qmlrefcount.cpp
new file mode 100644
index 0000000..4e47ee1
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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 "qmlrefcount_p.h"
+
+QmlRefCount::QmlRefCount()
+: refCount(1)
+{
+}
+
+QmlRefCount::~QmlRefCount()
+{
+}
+
+void QmlRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ ++refCount;
+}
+
+void QmlRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if(refCount == 0)
+ delete this;
+}
+
diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h
new file mode 100644
index 0000000..90b50a8
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QMLREFCOUNT_P_H
+#define QMLREFCOUNT_P_H
+
+#include <qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlRefCount
+{
+public:
+ QmlRefCount();
+ virtual ~QmlRefCount();
+ void addref();
+ void release();
+
+private:
+ int refCount;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLREFCOUNT_P_H
diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp
new file mode 100644
index 0000000..82d6eee
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** 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 <QtGui/qcolor.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include "qmlstringconverters_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static uchar fromHex(const uchar c, const uchar c2)
+{
+ uchar rv = 0;
+ if(c >= '0' && c <= '9')
+ rv += (c - '0') * 16;
+ else if(c >= 'A' && c <= 'F')
+ rv += (c - 'A' + 10) * 16;
+ else if(c >= 'a' && c <= 'f')
+ rv += (c - 'a' + 10) * 16;
+
+ if(c2 >= '0' && c2 <= '9')
+ rv += (c2 - '0');
+ else if(c2 >= 'A' && c2 <= 'F')
+ rv += (c2 - 'A' + 10);
+ else if(c2 >= 'a' && c2 <= 'f')
+ rv += (c2 - 'a' + 10);
+
+ return rv;
+}
+
+static uchar fromHex(const QString &s, int idx)
+{
+ uchar c = s.at(idx).toAscii();
+ uchar c2 = s.at(idx + 1).toAscii();
+ return fromHex(c, c2);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s)
+{
+ if(s.isEmpty())
+ return QVariant(s);
+ if(s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) {
+ QString data = s.mid(1, s.length() - 2);
+ return QVariant(data);
+ }
+ bool ok = false;
+ QRectF r = rectFFromString(s, &ok);
+ if(ok) return QVariant(r);
+ QColor c = colorFromString(s, &ok);
+ if(ok) return QVariant(c);
+ QPointF p = pointFFromString(s, &ok);
+ if(ok) return QVariant(p);
+ QSizeF sz = sizeFFromString(s, &ok);
+ if(ok) return QVariant(sz);
+ bool b = boolFromString(s, &ok);
+ if(ok) return QVariant(b);
+
+ return QVariant(s);
+}
+
+QColor QmlStringConverters::colorFromString(const QString &s, bool *ok)
+{
+ if(s.startsWith(QLatin1Char('#')) && s.length() == 9) {
+ uchar a = fromHex(s, 1);
+ uchar r = fromHex(s, 3);
+ uchar g = fromHex(s, 5);
+ uchar b = fromHex(s, 7);
+ if(ok) *ok = true;
+ return QColor(r, g, b, a);
+ } else {
+ QColor rv;
+ if(s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower()))
+ rv = QColor(s);
+ if(ok) *ok = rv.isValid();
+ return rv;
+ }
+}
+
+//expects input of "x,y"
+QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 1) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ bool xGood, yGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ if (!xGood || !yGood) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QPointF(xCoord, yCoord);
+}
+
+//expects input of "widthxheight"
+QSizeF QmlStringConverters::sizeFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ bool wGood, hGood;
+ int index = s.indexOf(QLatin1Char('x'));
+ qreal width = s.left(index).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QSizeF(width, height);
+}
+
+//expects input of "x,y,widthxheight" //### use space instead of second comma?
+QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ bool xGood, yGood, wGood, hGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal x = s.left(index).toDouble(&xGood);
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ index = s.indexOf(QLatin1Char('x'), index2+1);
+ qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!xGood || !yGood || !wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QRectF(x, y, width, height);
+}
+
+bool QmlStringConverters::boolFromString(const QString &str, bool *ok)
+{
+ if (str.isEmpty() || str == QLatin1String("false") || str == QLatin1String("0")) {
+ if (ok)
+ *ok = true;
+ return false;
+ } else if (str == QLatin1String("true") || str == QLatin1String("1")) {
+ if (ok)
+ *ok = true;
+ return true;
+ }
+
+ if (ok)
+ *ok = false;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h
new file mode 100644
index 0000000..ed1f959
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLSTRINGCONVERTERS_P_H
+#define QMLSTRINGCONVERTERS_P_H
+
+#include <QtCore/qglobal.h>
+class QColor;
+class QPointF;
+class QSizeF;
+class QRectF;
+class QString;
+class QByteArray;
+
+QT_BEGIN_NAMESPACE
+
+// XXX - Bauhaus currently uses these methods which is why they're exported
+namespace QmlStringConverters
+{
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &);
+ QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0);
+ QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0);
+ QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
+ QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0);
+ bool Q_DECLARATIVE_EXPORT boolFromString(const QString &, bool *ok = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTRINGCONVERTERS_P_H
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
new file mode 100644
index 0000000..966ef8a
--- /dev/null
+++ b/src/declarative/qml/qmlvme.cpp
@@ -0,0 +1,1345 @@
+/****************************************************************************
+**
+** 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 "qmlvme_p.h"
+#include <qfxperf.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlstringconverters_p.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <qml.h>
+#include <qmlcustomparser.h>
+#include <qperformancelog.h>
+#include <QStack>
+#include <private/qmlcompiledcomponent_p.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlcomponent.h>
+#include <qmlbindablevalue.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcomponent_p.h>
+#include "private/qmlvmemetaobject_p.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateCustomObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetId);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrSetDefault);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCreateComponent);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreMetaObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreReal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreInteger);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBool);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreString);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreColor);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDate);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreDateTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreTime);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStorePoint);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSize);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreVariant);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreSignal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreObjectQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignConstant);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignal);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignSignalObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignCompiledBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignValueSource);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreCompiledBinding);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreValueSource);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrTryBeginObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrBeginObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrTryCompleteObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrCompleteObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignObjectList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchAttached);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQmlList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrFetchObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrResolveFetchObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopFetchedObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPopQList);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrPushProperty);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrAssignStackObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrStoreStackObject);
+ Q_DECLARE_PERFORMANCE_METRIC(InstrNoOp);
+ Q_DECLARE_PERFORMANCE_METRIC(Dummy);
+}
+
+Q_DEFINE_PERFORMANCE_LOG(QFxCompiler, "QFxCompiler") {
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateObject, "CreateObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateCustomObject, "CreateCustomObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetId, "SetId");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrSetDefault, "SetDefault");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCreateComponent, "CreateComponent");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreMetaObject, "StoreMetaObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreReal, "StoreReal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreInteger, "StoreInteger");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBool, "StoreBool");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreString, "StoreString");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreColor, "StoreColor");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDate, "StoreDate");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreDateTime, "StoreDateTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreTime, "StoreTime");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStorePoint, "StorePoint(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSize, "StoreSize(F)");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreVariant, "StoreVariant");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObject, "StoreObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreSignal, "StoreSignal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreObjectQmlList, "StoreObjectQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignConstant, "AssignConstant");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignal, "AssignSignal");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignSignalObject, "AssignSignalObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignBinding, "AssignBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignCompiledBinding, "AssignCompiledBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignValueSource, "AssignValueSource");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreBinding, "StoreBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreCompiledBinding, "StoreCompiledBinding");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreValueSource, "StoreValueSource");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrTryBeginObject, "TryBeginObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrBeginObject, "BeginObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrTryCompleteObject, "TryCompleteObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrCompleteObject, "CompleteObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObject, "AssignObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignObjectList, "AssignObjectList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchAttached, "FetchAttached");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQmlList, "FetchQmlList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchQList, "FetchQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrFetchObject, "FetchObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrResolveFetchObject, "ResolveFetchObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopFetchedObject, "PopFetchedObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPopQList, "PopQList");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrPushProperty, "PushProperty");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrAssignStackObject, "AssignStackObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrStoreStackObject, "StoreStackObject");
+ Q_DEFINE_PERFORMANCE_METRIC(InstrNoOp, "NoOp");
+ Q_DEFINE_PERFORMANCE_METRIC(Dummy, "Dummy");
+}
+
+static inline int qIndexOfProperty(QObject *o, const char *name)
+{
+ int idx = o->metaObject()->indexOfProperty(name);
+ return idx;
+}
+
+QmlVME::QmlVME()
+: exceptionLine(-1)
+{
+}
+
+#define VME_EXCEPTION(desc) \
+ { \
+ exceptionLine = instr.line; \
+ QDebug d(&exceptionDescription); \
+ d << desc; \
+ break; \
+ }
+
+struct ListInstance
+{
+ ListInstance() {}
+ ListInstance(const QVariant &l, int t)
+ : list(l), type(t), qmlListInterface(0) {}
+ ListInstance(QmlPrivate::ListInterface *q, int t)
+ : type(t), qmlListInterface(q) {}
+
+ QVariant list;
+ int type;
+ QmlPrivate::ListInterface *qmlListInterface;
+};
+
+QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, int count)
+{
+ // XXX - All instances of QmlContext::activeContext() here should be
+ // replaced with the use of ctxt. However, this cannot be done until
+ // behaviours stop modifying the active context and expecting the
+ // instantiation to notice. Instead, QmlParserStatus::beginClass() should
+ // be able to return a QmlContext that is used for expressions and
+ // sub-instances on that type.
+ Q_ASSERT(comp);
+ Q_ASSERT(ctxt);
+ const QList<QmlCompiledComponent::TypeReference> &types = comp->types;
+ const QList<QString> &primitives = comp->primitives;
+ const QList<QByteArray> &datas = comp->datas;
+ const QList<QMetaObject *> &mos = comp->mos;
+ const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::CompileRun> cr;
+#endif
+
+ QList<QmlParserStatus *> parserStatuses;
+ QList<QmlBindableValue *> bindableValues;
+
+ QStack<QObject *> stack;
+ QStack<ListInstance> qliststack;
+
+ QStack<QmlMetaProperty> pushedProperties;
+ QObject **savedObjects = 0;
+
+ if(start == -1) start = 0;
+ if(count == -1) count = comp->bytecode.count();
+
+ for(int ii = start; !isError() && ii < (start + count); ++ii) {
+ QmlInstruction &instr = comp->bytecode[ii];
+
+ if(instr.type >= QmlInstruction::StoreInstructionsStart &&
+ instr.type <= QmlInstruction::StoreInstructionsEnd) {
+
+ runStoreInstruction(stack, instr, comp);
+
+ } else {
+
+ switch(instr.type) {
+ case QmlInstruction::Init:
+ {
+ if(instr.init.dataSize) {
+ savedObjects = new QObject*[instr.init.dataSize];
+ ::memset(savedObjects, 0,
+ sizeof(QObject *)*instr.init.dataSize);
+ }
+ }
+ break;
+
+ case QmlInstruction::CreateObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateObject> cc;
+#endif
+ QObject *o = types.at(instr.create.type).createInstance();
+ if(!o)
+ VME_EXCEPTION("Unable to create object of type" << types.at(instr.create.type).className);
+
+ if(!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ o->setParent(parent);
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::CreateCustomObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateCustomObject> cc;
+#endif
+ QVariant v =
+ types.at(instr.createCustom.type).parser->create(datas.at(instr.createCustom.data));
+ // XXX
+ QObject *o = QmlMetaType::toQObject(v);
+ if(!o)
+ VME_EXCEPTION("Unable to create" << types.at(instr.create.type).className);
+
+ if(!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ o->setParent(parent);
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::SetId:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetId> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext *ctxt =
+ QmlContext::activeContext();
+ ctxt->setContextProperty(primitives.at(instr.setId.value), target);
+
+ if(instr.setId.save != -1)
+ savedObjects[instr.setId.save] = target;
+ }
+ break;
+
+
+ case QmlInstruction::SetDefault:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrSetDefault> cc;
+#endif
+ QObject *target = stack.top();
+ QmlContext::activeContext()->addDefaultObject(target);
+ }
+ break;
+
+ case QmlInstruction::CreateComponent:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCreateComponent> cc;
+#endif
+ QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top());
+ stack.push(qcomp);
+ ii += instr.createComponent.count;
+ }
+ break;
+
+ case QmlInstruction::StoreMetaObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreMetaObject> cc;
+#endif
+ QObject *target = stack.top();
+ new QmlVMEMetaObject(target, mos.at(instr.storeMeta.data), comp);
+ }
+ break;
+
+ case QmlInstruction::AssignCustomType:
+ {
+ QObject *target = stack.top();
+ void *a[1];
+ QmlCompiledComponent::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
+ const QString &primitive = primitives.at(data.index);
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(data.type);
+ QVariant v = (*converter)(primitive);
+
+ QMetaProperty prop =
+ target->metaObject()->property(instr.assignCustomType.propertyIndex);
+ if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
+ VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name());
+
+ a[0] = (void *)v.data();
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.assignCustomType.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::AssignSignal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignSignal> cc;
+#endif
+ // Fixup instruction
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignal.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QLatin1String(pr));
+ if(prop.type() & QmlMetaProperty::SignalProperty) {
+ int coreIdx = prop.coreIndex();
+ int primRef = instr.assignSignal.value;
+ instr.type = QmlInstruction::StoreSignal;
+ instr.storeSignal.signalIndex = coreIdx;
+ instr.storeSignal.value = primRef;
+ --ii;
+ } else if(prop.type() & QmlMetaProperty::Property) {
+ int prop = sigIdx;
+ int primRef = instr.assignSignal.value;
+ instr.type = QmlInstruction::AssignConstant;
+ instr.assignConstant.property = prop;
+ instr.assignConstant.constant = primRef;
+ --ii;
+ } else {
+ VME_EXCEPTION("Cannot assign a signal to property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignSignalObject> cc;
+#endif
+ // XXX optimize
+
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignalObject.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QLatin1String(pr));
+ if(prop.type() & QmlMetaProperty::SignalProperty) {
+
+ QMetaMethod method = QmlMetaType::defaultMethod(assign);
+ if(method.signature() == 0)
+ VME_EXCEPTION("Cannot assign object type" << assign->metaObject()->className() << "with no default method");
+
+ if(!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+ VME_EXCEPTION("Cannot connect mismatched signal/slot" << method.signature() << prop.method().signature());
+
+ QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex());
+
+ } else if(prop.type() & QmlMetaProperty::Property) {
+ instr.type = QmlInstruction::AssignObject;
+ instr.assignObject.castValue = 0;
+ instr.assignObject.property = sigIdx;
+ --ii;
+ } else {
+ VME_EXCEPTION("Cannot assign an object to signal property" << pr);
+ }
+
+
+ }
+ break;
+
+ case QmlInstruction::StoreSignal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSignal> cc;
+#endif
+ QObject *target = stack.top();
+ // XXX scope
+ QMetaMethod signal =
+ target->metaObject()->method(instr.storeSignal.signalIndex);
+
+ if(signal.parameterTypes().isEmpty()) {
+ (void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ } else {
+ (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignConstant:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignConstant> cc;
+#endif
+ // Fixup instruction
+ QObject *target = stack.top();
+ int propIdx = instr.assignConstant.property;
+ int idx = instr.assignConstant.constant;
+ QByteArray pr;
+ if(propIdx == -1) {
+ pr = QmlMetaType::defaultProperty(target).name();
+ if(pr.isEmpty())
+ VME_EXCEPTION("Cannot resolve defalt property on type" << target->metaObject()->className());
+ } else {
+ pr = datas.at(propIdx);
+ }
+
+ int coreIdx = qIndexOfProperty(target, pr);
+
+ if(coreIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(coreIdx);
+ bool replace = !prop.isDynamic();
+
+ QmlInstruction *writeInstr = 0;
+ QmlInstruction dummy;
+ if(replace) {
+ writeInstr = &instr;
+ } else {
+ writeInstr = &dummy;
+ dummy = instr;
+ }
+
+ QmlCompiler::StoreInstructionResult r = QmlCompiler::generateStoreInstruction(*comp, *writeInstr, prop,
+ coreIdx, idx, &primitives.at(idx));
+ if(r != QmlCompiler::Ok) {
+ if(prop.isEnumType()){
+ VME_EXCEPTION(primitives.at(idx) << "is not a valid enumeration value");
+ } else if (r == QmlCompiler::UnknownType) {
+ VME_EXCEPTION("Property" << prop.name() << "is of an unknown type");
+ } else if (r == QmlCompiler::InvalidData) {
+ VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to property" << prop.name());
+ } else if (r == QmlCompiler::ReadOnly) {
+ VME_EXCEPTION("Cannot assign value" << primitives.at(idx) << "to read-only property" << prop.name());
+ } else {
+ VME_EXCEPTION("Invalid property assignment for property" << prop.name());
+ }
+ } else {
+ runStoreInstruction(stack, *writeInstr, comp);
+ }
+
+ } else {
+ VME_EXCEPTION("Unknown property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::TryBeginObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrTryBeginObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status =
+ qobject_cast<QmlParserStatus *>(target);
+
+ if(status) {
+ instr.type = QmlInstruction::BeginObject;
+ instr.begin.castValue = int(reinterpret_cast<char *>(status) - reinterpret_cast<char *>(target));
+ --ii;
+ } else {
+ instr.type = QmlInstruction::NoOp;
+ }
+ }
+ break;
+
+ case QmlInstruction::BeginObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrBeginObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ status->classBegin();
+ parserStatuses << status;
+ }
+ break;
+
+ case QmlInstruction::TryCompleteObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrTryCompleteObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status =
+ qobject_cast<QmlParserStatus *>(target);
+
+ if(status) {
+ instr.type = QmlInstruction::CompleteObject;
+ instr.complete.castValue = int(reinterpret_cast<char *>(status) - reinterpret_cast<char *>(target));
+ --ii;
+ } else {
+ instr.type = QmlInstruction::NoOp;
+ }
+ }
+ break;
+
+ case QmlInstruction::CompleteObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrCompleteObject> cc;
+#endif
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.complete.castValue);
+ status->classComplete();
+ }
+ break;
+
+ case QmlInstruction::AssignCompiledBinding:
+ case QmlInstruction::AssignBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignBinding> cc;
+#endif
+ QObject *target = stack.top();
+ const QByteArray &pr = datas.at(instr.fetch.property);
+ int idx = qIndexOfProperty(target, pr);
+
+ // XXX - need to check if the type is QmlBindableValue*
+ if(idx == -1) {
+ VME_EXCEPTION("Unknown property" << pr);
+ } else {
+ if(QmlInstruction::AssignCompiledBinding == instr.type)
+ instr.type = QmlInstruction::StoreCompiledBinding;
+ else
+ instr.type = QmlInstruction::StoreBinding;
+ instr.assignBinding.property = idx;
+ instr.assignBinding.category = QmlMetaProperty::Unknown;
+ }
+ ii--;
+ }
+ break;
+
+ case QmlInstruction::AssignValueSource:
+ {
+ QObject *target = stack.at(stack.count() - 2);
+ int propIdx = instr.assignValueSource.property;
+ QByteArray pr;
+ if(propIdx == -1) {
+ pr = QmlMetaType::defaultProperty(target).name();
+ if(pr.isEmpty())
+ VME_EXCEPTION("Unable to resolve default property");
+ } else {
+ pr = datas.at(propIdx);
+ }
+
+ int coreIdx = qIndexOfProperty(target, pr);
+ if(coreIdx != -1) {
+ instr.type = QmlInstruction::StoreValueSource;
+ instr.assignValueSource.property = coreIdx;
+ ii--;
+ } else {
+ VME_EXCEPTION("Unknown property" << pr);
+ }
+ }
+ break;
+
+ case QmlInstruction::PushProperty:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPushProperty> cc;
+#endif
+ QObject *target = stack.top();
+ QmlMetaProperty mp(target, instr.pushProperty.property,
+ QmlMetaProperty::Object);
+ pushedProperties.push(mp);
+ }
+ break;
+
+ case QmlInstruction::StoreCompiledBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreCompiledBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+ if (!mp.isWritable())
+ VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
+
+ QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, 0);
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ bindableValues << bind;
+ }
+ break;
+
+ case QmlInstruction::StoreBinding:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBinding> cc;
+#endif
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp(target, instr.assignBinding.property,
+ (QmlMetaProperty::PropertyCategory)instr.assignBinding.category);
+ if (!mp.isWritable())
+ VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
+
+ QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, false);
+ QFx_setParent_noEvent(bind, target);
+
+ bind->setTarget(mp);
+ bindableValues << bind;
+ }
+ break;
+
+ case QmlInstruction::StoreValueSource:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreValueSource> cc;
+#endif
+ QObject *assign = stack.pop();
+ QmlPropertyValueSource *vs =
+ static_cast<QmlPropertyValueSource *>(assign);
+ QObject *target = stack.top();
+ vs->setParent(target);
+ vs->setTarget(QmlMetaProperty(target, instr.assignValueSource.property));
+ }
+ break;
+
+ case QmlInstruction::AssignObjectList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignObjectList> cc;
+#endif
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+ if(list.qmlListInterface) {
+ int type = list.type;
+
+ void *d = 0;
+ void *ptr = 0;
+ bool found = false;
+
+ if(QmlMetaType::isInterface(type)) {
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if(iid)
+ ptr = assign->qt_metacast(iid);
+ if(ptr) {
+ d = &ptr;
+ found = true;
+ }
+ } else {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *assignMo = assign->metaObject();
+ while(!found && assignMo) {
+ if(assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ d = (void *)&assign;
+ }
+
+
+ if(!found)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ list.qmlListInterface->append(d);
+
+ } else {
+ int type = list.type;
+
+ if(QmlMetaType::isInterface(type)) {
+ void *ptr = 0;
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if(iid)
+ ptr = assign->qt_metacast(iid);
+ QVariant v(list.type, &ptr);
+ QmlMetaType::append(list.list, v);
+ } else {
+ QVariant v = QmlMetaType::fromObject(assign, list.type);
+ QmlMetaType::append(list.list, v);
+ }
+ }
+ }
+ break;
+
+ case QmlInstruction::AssignObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignObject> cc;
+#endif
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ QByteArray property;
+ if(instr.assignObject.property == -1) {
+ // XXX - optimize!
+ property =
+ QmlMetaType::defaultProperty(target).name();
+ } else {
+ property = datas.at(instr.assignObject.property);
+ }
+
+ int coreIdx = qIndexOfProperty(target, property);
+
+ if(coreIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(coreIdx);
+ int t = prop.userType();
+ // XXX - optimize!
+ if(QmlMetaType::isList(t)) {
+ QVariant list = prop.read(target);
+ int listtype = QmlMetaType::listType(t);
+ QVariant v = QmlMetaType::fromObject(assign, listtype);
+ QmlMetaType::append(list, v);
+ } else if(QmlMetaType::isQmlList(t)) {
+
+ // XXX - optimize!
+ QVariant list = prop.read(target);
+ QmlPrivate::ListInterface *li =
+ *(QmlPrivate::ListInterface **)list.constData();
+
+ int type = li->type();
+
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *assignMo = assign->metaObject();
+ bool found = false;
+ while(!found && assignMo) {
+ if(assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ if(!found)
+ VME_EXCEPTION("Cannot assign object to list");
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&assign;
+ li->append(d);
+
+ } else if(QmlMetaType::isInterface(t)) {
+ const char *iid = QmlMetaType::interfaceIId(t);
+ bool ok = false;
+ if(iid) {
+ void *ptr = assign->qt_metacast(iid);
+ if(ptr) {
+ void *a[1];
+ a[0] = &ptr;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ coreIdx, a);
+ ok = true;
+ }
+ }
+
+ if(!ok)
+ VME_EXCEPTION("Cannot assign object to interface property" << property);
+
+ } else if(prop.userType() == -1 /* means qvariant */) {
+ prop.write(target, qVariantFromValue(assign));
+ } else {
+ const QMetaObject *propmo =
+ QmlMetaType::rawMetaObjectForType(t);
+
+ bool isPropertyValue = false;
+ bool isAssignable = false;
+ const QMetaObject *c = assign->metaObject();
+ while(c) {
+ isPropertyValue = isPropertyValue || (c == &QmlPropertyValueSource::staticMetaObject);
+ isAssignable = isAssignable || (c == propmo);
+ c = c->superClass();
+ }
+
+ if(isAssignable) {
+ // XXX - optimize!
+ QVariant v = QmlMetaType::fromObject(assign, t);
+ prop.write(target, v);
+ } else if(isPropertyValue) {
+ QmlPropertyValueSource *vs =
+ static_cast<QmlPropertyValueSource *>(assign);
+ vs->setParent(target);
+ vs->setTarget(QmlMetaProperty(target, coreIdx));
+ } else {
+ VME_EXCEPTION("Cannot assign to" << property);
+ }
+ }
+
+
+ } else {
+ VME_EXCEPTION("Cannot assign to non-existant property" << property);
+ }
+
+ }
+ break;
+
+ case QmlInstruction::FetchAttached:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchAttached> cc;
+#endif
+ QObject *target = stack.top();
+
+ QmlAttachedPropertiesFunc attachFunc =
+ QmlMetaType::attachedPropertiesFunc(datas.at(instr.fetchAttached.idx));
+ if(!attachFunc)
+ VME_EXCEPTION("No such attached object" << primitives.at(instr.fetchAttached.idx));
+
+ QObject *qmlObject = attachFunc(target);
+ if(!qmlObject)
+ VME_EXCEPTION("Internal error - unable to create attached object" << primitives.at(instr.fetchAttached.idx));
+
+ stack.push(qmlObject);
+ }
+ break;
+
+ case QmlInstruction::FetchQmlList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQmlList> cc;
+#endif
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QmlList<*> can be converted to
+ // QmlPrivate::ListInterface
+ QmlPrivate::ListInterface *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if(!list)
+ VME_EXCEPTION("Cannot assign to null list");
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchQList> cc;
+#endif
+ QObject *target = stack.top();
+ QMetaProperty prop =
+ target->metaObject()->property(instr.fetch.property);
+ QVariant v = prop.read(target);
+ qliststack.push(ListInstance(v, QmlMetaType::listType(prop.userType())));
+ }
+ break;
+
+ case QmlInstruction::ResolveFetchObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrResolveFetchObject> cc;
+#endif
+ QObject *target = stack.top();
+ const QByteArray &pr = datas.at(instr.fetch.property);
+ int idx = qIndexOfProperty(target, pr);
+ if(idx == -1)
+ VME_EXCEPTION("Cannot resolve property" << pr);
+ QMetaProperty prop = target->metaObject()->property(idx);
+ instr.type = QmlInstruction::FetchObject;
+ instr.fetch.property = idx;
+ if(QmlMetaType::isObject(prop.userType())) {
+ instr.fetch.isObject = true;
+ } else if(prop.userType() == -1) {
+ instr.fetch.isObject = false;
+ } else {
+ VME_EXCEPTION("Cannot set properties on" << prop.name() << "as it is of unknown type");
+ }
+ ii--;
+ }
+ break;
+
+ case QmlInstruction::FetchObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrFetchObject> cc;
+#endif
+ QObject *target = stack.top();
+
+ QObject *obj = 0;
+ if(instr.fetch.isObject) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ } else {
+ void *a[1];
+ QVariant var;
+ a[0] = &var;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+ obj = QmlMetaType::toQObject(var);
+
+ }
+
+ if(!obj)
+ VME_EXCEPTION("Cannot set properties on" << target->metaObject()->property(instr.fetch.property).name() << "as it is null");
+
+ stack.push(obj);
+ }
+ break;
+
+ case QmlInstruction::PopQList:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopQList> cc;
+#endif
+ qliststack.pop();
+ }
+ break;
+
+ case QmlInstruction::PopFetchedObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrPopFetchedObject> cc;
+#endif
+ stack.pop();
+ }
+ break;
+
+ case QmlInstruction::AssignStackObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrAssignStackObject> cc;
+#endif
+
+ QObject *obj = savedObjects[instr.assignStackObject.object];
+ const QmlMetaProperty &prop =
+ pushedProperties.at(instr.assignStackObject.property);
+
+
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(prop.propertyType());
+ const QMetaObject *assignMo = obj->metaObject();
+
+ bool found = false;
+ while(!found && assignMo) {
+ if(assignMo == mo)
+ found = true;
+ else
+ assignMo = assignMo->superClass();
+ }
+
+ if(!found)
+ VME_EXCEPTION("Unable to assign object");
+
+ instr.type = QmlInstruction::StoreStackObject;
+ --ii;
+ }
+ break;
+
+ case QmlInstruction::StoreStackObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreStackObject> cc;
+#endif
+
+ const QmlMetaProperty &prop =
+ pushedProperties.at(instr.assignStackObject.property);
+ QObject *obj = savedObjects[instr.assignStackObject.object];
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = (void *)&obj;
+ QMetaObject::metacall(prop.object(), QMetaObject::WriteProperty,
+ prop.coreIndex(), a);
+ }
+ break;
+
+ case QmlInstruction::NoOp:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrNoOp> cc;
+#endif
+ }
+ break;
+
+ default:
+ qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+ }
+ }
+
+ if(isError()) {
+ if(!stack.isEmpty()) {
+ delete stack.at(0);
+ }
+ return 0;
+ }
+
+ QmlEnginePrivate *ep = ctxt->engine()->d_func();
+ ep->currentBindValues << bindableValues;
+ ep->currentParserStatus << parserStatuses;
+
+ comp->dumpPost();
+
+ if(savedObjects)
+ delete [] savedObjects;
+
+ if(stack.isEmpty())
+ return 0;
+ else
+ return stack.top();
+ return 0;
+}
+
+bool QmlVME::isError() const
+{
+ return exceptionLine != -1;
+}
+
+qint64 QmlVME::errorLine() const
+{
+ return exceptionLine;
+}
+
+QString QmlVME::errorDescription() const
+{
+ return exceptionDescription;
+}
+
+void QmlVME::runStoreInstruction(QStack<QObject *> &stack,
+ QmlInstruction &instr,
+ QmlCompiledData *comp)
+{
+ const QList<QString> &primitives = comp->primitives;
+ const QList<int> &intData = comp->intData;
+ const QList<float> &floatData = comp->floatData;
+
+ switch(instr.type) {
+ case QmlInstruction::StoreVariant:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreVariant> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ // XXX - can be more efficient
+ QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
+ a[0] = (void *)&v;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreString:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreString> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&primitives.at(instr.storeString.value);
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreReal:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreReal> cc;
+#endif
+ QObject *target = stack.top();
+ qreal r = instr.storeReal.value;
+ void *a[1];
+ a[0] = &r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreBool:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreBool> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeBool.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeBool.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInteger:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreInteger> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ a[0] = (void *)&instr.storeInteger.value;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeReal.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreColor:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreColor> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QColor c = QColor::fromRgba(instr.storeColor.value);
+ a[0] = (void *)&c;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeColor.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDate:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreDate> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QDate d = QDate::fromJulianDay(instr.storeDate.value);
+ a[0] = (void *)&d;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDate.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeTime.valueIndex),
+ intData.at(instr.storeTime.valueIndex+1),
+ intData.at(instr.storeTime.valueIndex+2),
+ intData.at(instr.storeTime.valueIndex+3));
+ a[0] = (void *)&t;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDateTime:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreDateTime> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QTime t;
+ t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
+ intData.at(instr.storeDateTime.valueIndex+2),
+ intData.at(instr.storeDateTime.valueIndex+3),
+ intData.at(instr.storeDateTime.valueIndex+4));
+ QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
+ a[0] = (void *)&dt;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDateTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePoint:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePointF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStorePoint> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QPointF p(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSize:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
+ a[0] = (void *)&p;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSizeF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreSize> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ a[0] = (void *)&s;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRect:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3)).toRect();
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRectF:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ //QFxCompilerTimer<QFxCompiler::InstrStoreRect> cc;
+#endif
+ QObject *target = stack.top();
+ void *a[1];
+ QRectF r(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3));
+ a[0] = (void *)&r;
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreObject:
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxCompilerTimer<QFxCompiler::InstrStoreObject> cc;
+#endif
+ QObject *assignObj = stack.pop();
+ QObject *target = stack.top();
+
+ void *a[1];
+ void *obj = (void *)(((char *)assignObj) + instr.storeObject.cast);
+ a[0] = (void *)&obj;
+
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+ default:
+ qFatal("QmlCompiledComponent: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
new file mode 100644
index 0000000..2a3be06
--- /dev/null
+++ b/src/declarative/qml/qmlvme_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 QMLVME_P_H
+#define QMLVME_P_H
+
+#include <QString>
+#include <QStack>
+class QObject;
+
+QT_BEGIN_NAMESPACE
+class QmlInstruction;
+class QmlCompiledComponent;
+class QmlCompiledData;
+class QmlContext;
+
+class QmlVME
+{
+public:
+ QmlVME();
+
+ QObject *run(QmlContext *, QmlCompiledComponent *, int start = -1, int end = -1);
+
+ bool isError() const;
+ qint64 errorLine() const;
+ QString errorDescription() const;
+
+private:
+ void runStoreInstruction(QStack<QObject *> &stack,
+ QmlInstruction &, QmlCompiledData *);
+
+ qint64 exceptionLine;
+ QString exceptionDescription;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVME_P_H
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
new file mode 100644
index 0000000..2b1060b
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** 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 "qmlvmemetaobject_p.h"
+#include <qml.h>
+#include <private/qmlrefcount_p.h>
+#include <QColor>
+#include <QDate>
+
+
+QT_BEGIN_NAMESPACE
+QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
+ const QMetaObject *other,
+ QmlRefCount *rc)
+: object(obj), ref(rc)
+{
+ if(ref)
+ ref->addref();
+
+ *static_cast<QMetaObject *>(this) = *other;
+ this->d.superdata = obj->metaObject();
+ QObjectPrivate::get(obj)->metaObject = this;
+
+ baseProp = propertyOffset();
+ baseSig = methodOffset();
+ data = new QVariant[propertyCount() - baseProp];
+ vTypes.resize(propertyCount() - baseProp);
+
+ for(int ii = baseProp; ii < propertyCount(); ++ii) {
+ QMetaProperty prop = property(ii);
+ if((int)prop.type() != -1) {
+ data[ii - baseProp] = QVariant((QVariant::Type)prop.userType());
+ } else {
+ vTypes.setBit(ii - baseProp, true);
+ }
+ }
+}
+
+QmlVMEMetaObject::~QmlVMEMetaObject()
+{
+ if(ref)
+ ref->release();
+ delete [] data;
+}
+
+int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if(id >= baseProp) {
+ int propId = id - baseProp;
+ bool needActivate = false;
+
+ if(vTypes.testBit(propId)) {
+ if(c == QMetaObject::ReadProperty) {
+ *reinterpret_cast<QVariant *>(a[0]) = data[propId];
+ } else if(c == QMetaObject::WriteProperty) {
+ needActivate =
+ (data[propId] != *reinterpret_cast<QVariant *>(a[0]));
+ data[propId] = *reinterpret_cast<QVariant *>(a[0]);
+ }
+ } else {
+ if(c == QMetaObject::ReadProperty) {
+ switch(data[propId].type()) {
+ case QVariant::Int:
+ *reinterpret_cast<int *>(a[0]) = data[propId].toInt();
+ break;
+ case QVariant::Bool:
+ *reinterpret_cast<bool *>(a[0]) = data[propId].toBool();
+ break;
+ case QVariant::Double:
+ *reinterpret_cast<double *>(a[0]) = data[propId].toDouble();
+ break;
+ case QVariant::String:
+ *reinterpret_cast<QString *>(a[0]) = data[propId].toString();
+ break;
+ case QVariant::Color:
+ *reinterpret_cast<QColor *>(a[0]) = data[propId].value<QColor>();
+ break;
+ case QVariant::Date:
+ *reinterpret_cast<QDate *>(a[0]) = data[propId].toDate();
+ break;
+ default:
+ qFatal("Unknown type");
+ break;
+ }
+ } else if(c == QMetaObject::WriteProperty) {
+
+ QVariant value = QVariant((QVariant::Type)data[propId].type(), a[0]);
+ needActivate = (data[propId] != value);
+ data[propId] = value;
+ }
+ }
+
+ if(c == QMetaObject::WriteProperty && needActivate) {
+ activate(object, baseSig + propId, 0);
+ }
+
+ return id;
+ } else {
+ return object->qt_metacall(c, id, a);
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
new file mode 100644
index 0000000..3fb1c46
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 QMLVMEMETAOBJECT_P_H
+#define QMLVMEMETAOBJECT_P_H
+
+#include <qml.h>
+#include <QMetaObject>
+#include <QBitArray>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+class QmlRefCount;
+class QmlVMEMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlVMEMetaObject(QObject *, const QMetaObject *, QmlRefCount * = 0);
+ ~QmlVMEMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QObject *object;
+ QmlRefCount *ref;
+ int baseProp;
+ int baseSig;
+ QVariant *data;
+ QBitArray vTypes;
+};
+
+QT_END_NAMESPACE
+#endif // QMLVMEMETAOBJECT_P_H
diff --git a/src/declarative/qml/qmlxmlparser.cpp b/src/declarative/qml/qmlxmlparser.cpp
new file mode 100644
index 0000000..f001bda
--- /dev/null
+++ b/src/declarative/qml/qmlxmlparser.cpp
@@ -0,0 +1,384 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlxmlparser_p.h"
+#include "qmlcustomparser.h"
+#include <qfxperf.h>
+#include <QXmlStreamReader>
+#include <QStack>
+#include "qmlparser_p.h"
+#include <private/qmlparser_p.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+using namespace QmlParser;
+
+struct QmlXmlParserState {
+ QmlXmlParserState() : object(0), property(0) {}
+ QmlXmlParserState(Object *o) : object(o), property(0) {}
+ QmlXmlParserState(Object *o, Property *p) : object(o), property(p) {}
+
+ Object *object;
+ Property *property;
+};
+
+struct QmlXmlParserStateStack : public QStack<QmlXmlParserState>
+{
+ void pushObject(Object *obj)
+ {
+ push(QmlXmlParserState(obj));
+ }
+
+ void pushProperty(const QString &name, int lineNumber)
+ {
+ const QmlXmlParserState &state = top();
+ if(state.property) {
+ QmlXmlParserState s(state.property->getValue(),
+ state.property->getValue()->getProperty(name.toLatin1()));
+ s.property->line = lineNumber;
+ push(s);
+ } else {
+ QmlXmlParserState s(state.object,
+ state.object->getProperty(name.toLatin1()));
+ s.property->line = lineNumber;
+ push(s);
+ }
+ }
+};
+
+QmlXmlParser::~QmlXmlParser()
+{
+ if(root)
+ root->release();
+}
+
+QmlXmlParser::QmlXmlParser()
+: root(0)
+{
+}
+
+static QString flatXml(QXmlStreamReader& reader)
+{
+ QString result;
+ int depth=0;
+ QStringRef ns = reader.namespaceUri();
+ while (depth>=0) {
+ switch (reader.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ result += QLatin1Char('<');
+ result += reader.name();
+ if (reader.namespaceUri() != ns || depth==0) {
+ result += QLatin1String(" xmlns=\"");
+ result += reader.namespaceUri();
+ result += QLatin1Char('"');
+ }
+ foreach(QXmlStreamAttribute attr, reader.attributes()) {
+ result += QLatin1Char(' ');
+ result += attr.name();
+ result += QLatin1String("=\"");
+ result += attr.value(); // XXX escape
+ result += QLatin1Char('"');
+ }
+ result += QLatin1Char('>');
+ ++depth;
+ break;
+ case QXmlStreamReader::EndElement:
+ result += QLatin1String("</");
+ result += reader.name();
+ result += QLatin1Char('>');
+ --depth;
+ break;
+ case QXmlStreamReader::Characters:
+ result += reader.text();
+ break;
+ default:
+ reader.raiseError(QLatin1String("Only StartElement, EndElement, and Characters permitted"));
+ break;
+ }
+ if (depth>=0)
+ reader.readNext();
+ }
+ return result;
+}
+
+bool QmlXmlParser::parse(const QByteArray &data, const QUrl &url)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::XmlParsing> pt;
+#endif
+
+ QString fileDisplayName;
+ if (url.isEmpty()) {
+ fileDisplayName = QLatin1String("<unspecified file>");
+ } else if (url.scheme() == QLatin1String("file")) {
+ fileDisplayName = url.toLocalFile();
+ } else {
+ fileDisplayName = url.toString();
+ }
+ if (data.isEmpty()) {
+ _error = QLatin1String("No Qml was specified for parsing @") + fileDisplayName;
+ return false;
+ }
+
+ QmlXmlParserStateStack states;
+
+ QXmlStreamReader reader;
+ reader.addData(data);
+
+ while(!reader.atEnd()) {
+ switch(reader.readNext()) {
+ case QXmlStreamReader::Invalid:
+ case QXmlStreamReader::NoToken:
+ case QXmlStreamReader::StartDocument:
+ case QXmlStreamReader::EndDocument:
+ break;
+
+ case QXmlStreamReader::StartElement:
+ {
+ QString name = reader.name().toString();
+ QString nameSpace = reader.namespaceUri().toString();
+ int line = reader.lineNumber();
+ bool isType = name.at(0).isUpper() && !name.contains(QLatin1Char('.'));
+ QString qualifiedname;
+ if (!nameSpace.isEmpty()) {
+ qualifiedname = nameSpace;
+ qualifiedname += QLatin1Char('/');
+ }
+ qualifiedname += name;
+ QByteArray qualifiednameL1 = qualifiedname.toLatin1();
+ QXmlStreamAttributes attrs = reader.attributes();
+
+ if (isType) {
+ // Class
+ int typeId = _typeNames.indexOf(qualifiedname);
+ if(typeId == -1) {
+ typeId = _typeNames.count();
+ _typeNames.append(qualifiedname);
+ }
+
+ Object *obj = new Object;
+ obj->type = typeId;
+ obj->typeName = qualifiednameL1;
+ obj->line = line;
+
+ QmlCustomParser *customparser = QmlMetaType::customParser(qualifiednameL1);
+ if (customparser) {
+ bool ok;
+ obj->custom = customparser->compile(reader, &ok);
+ if (reader.tokenType() != QXmlStreamReader::EndElement) {
+ reader.raiseError(QLatin1String("Parser for ") + qualifiedname + QLatin1String(" did not end on end element"));
+ ok = false;
+ }
+ if (!ok) {
+ delete obj;
+ break;
+ }
+ }
+
+
+ if(!root) {
+ root = obj;
+ states.pushObject(obj);
+ } else {
+ const QmlXmlParserState &state = states.top();
+ Value *v = new Value;
+ v->object = obj;
+ v->line = line;
+ if(state.property)
+ state.property->addValue(v);
+ else
+ state.object->getDefaultProperty()->addValue(v);
+ states.pushObject(obj);
+ }
+ } else {
+ // Property
+ if (!root) {
+ reader.raiseError(QLatin1String("Can't have a property with no object"));
+ break;
+ }
+ QStringList str = name.split(QLatin1Char('.'));
+ for(int ii = 0; ii < str.count(); ++ii) {
+ QString s = str.at(ii);
+ states.pushProperty(s, line);
+ }
+ if (!nameSpace.isEmpty()) {
+ // Pass non-QML as flat text property value
+ const QmlXmlParserState &state = states.top();
+ Value *v = new Value;
+ v->primitive = flatXml(reader);
+ v->line = line;
+ state.property->addValue(v);
+ }
+ }
+
+ // (even custom parsed content gets properties set)
+ foreach(QXmlStreamAttribute attr, attrs) {
+ QStringList str = attr.name().toString().split(QLatin1Char('.'));
+
+ for(int ii = 0; ii < str.count(); ++ii) {
+ QString s = str.at(ii);
+ states.pushProperty(s, line);
+ }
+
+ const QmlXmlParserState &state = states.top();
+ Value *v = new Value;
+ v->primitive = attr.value().toString();
+ v->line = reader.lineNumber();
+ state.property->addValue(v);
+
+ for(int ii = str.count() - 1; ii >= 0; --ii)
+ states.pop();
+ }
+ }
+
+ // Custom parsers and namespaced properties move
+ // the reader to the end element, so we handle that
+ // BEFORE continuing.
+ //
+ if (reader.tokenType()!=QXmlStreamReader::EndElement)
+ break;
+ // ELSE fallthrough to EndElement...
+ case QXmlStreamReader::EndElement:
+ {
+ QString name = reader.name().toString();
+ Q_ASSERT(!name.isEmpty());
+ if(name.at(0).isUpper() && !name.contains(QLatin1Char('.'))) {
+ // Class
+ states.pop();
+ } else {
+ // Property
+ QStringList str = name.split(QLatin1Char('.'));
+ for(int ii = 0; ii < str.count(); ++ii)
+ states.pop();
+ }
+ }
+ break;
+ case QXmlStreamReader::Characters:
+ if(!reader.isWhitespace()) {
+ const QmlXmlParserState &state = states.top();
+ Value *v = new Value;
+ v->primitive = reader.text().toString();
+ v->line = reader.lineNumber();
+ if(state.property)
+ state.property->addValue(v);
+ else
+ state.object->getDefaultProperty()->addValue(v);
+ }
+ break;
+
+ case QXmlStreamReader::Comment:
+ case QXmlStreamReader::DTD:
+ case QXmlStreamReader::EntityReference:
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ if(reader.processingInstructionTarget() == QLatin1String("qtfx")) {
+ QString str = reader.processingInstructionData().toString();
+ QString token, data;
+ int idx = str.indexOf(QLatin1Char(':'));
+ if(-1 != idx) {
+ token = str.left(idx);
+ data = str.mid(idx + 1);
+ } else {
+ token = str;
+ }
+ token = token.trimmed();
+ data = data.trimmed();
+
+ // <?qtfx namespacepath: namespace=path>
+
+ if(token == QLatin1String("namespacepath")) {
+ int eq=data.indexOf(QLatin1Char('='));
+ if (eq>=0) {
+ _nameSpacePaths.insertMulti(data.left(eq),data.mid(eq+1));
+ }
+ } else {
+ str = str.trimmed();
+ qWarning().nospace() << "Unknown processing instruction " << str.toLatin1().constData() << " @" << fileDisplayName.toLatin1().constData() << ":" << reader.lineNumber();
+ }
+ }
+ break;
+ }
+ }
+
+ if(reader.hasError()) {
+ if (root) {
+ root->release();
+ root = 0;
+ }
+ _error = reader.errorString() + QLatin1String(" @") + fileDisplayName +
+ QLatin1String(":") + QString::number(reader.lineNumber());
+ }
+
+ return root != 0;
+}
+
+QMap<QString,QString> QmlXmlParser::nameSpacePaths() const
+{
+ return _nameSpacePaths;
+}
+
+QStringList QmlXmlParser::types() const
+{
+ return _typeNames;
+}
+
+QmlParser::Object *QmlXmlParser::tree() const
+{
+ return root;
+}
+
+QString QmlXmlParser::errorDescription() const
+{
+ return _error;
+}
+
+void QmlXmlParser::clear()
+{
+ if(root) {
+ root->release();
+ root = 0;
+ }
+ _nameSpacePaths.clear();
+ _typeNames.clear();
+ _error.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlxmlparser_p.h b/src/declarative/qml/qmlxmlparser_p.h
new file mode 100644
index 0000000..3680172
--- /dev/null
+++ b/src/declarative/qml/qmlxmlparser_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLXMLPARSER_P_H
+#define QMLXMLPARSER_P_H
+
+#include <QList>
+#include <QUrl>
+#include <qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace QmlParser {
+ class Object;
+}
+
+class QByteArray;
+class QmlXmlParser
+{
+public:
+ QmlXmlParser();
+ ~QmlXmlParser();
+
+ bool parse(const QByteArray &data, const QUrl &url=QUrl());
+ QString errorDescription() const;
+
+ QMap<QString,QString> nameSpacePaths() const;
+ QStringList types() const;
+
+ QmlParser::Object *tree() const;
+
+ void clear();
+
+private:
+ QMap<QString,QString> _nameSpacePaths;
+ QmlParser::Object *root;
+ QStringList _typeNames;
+ QString _error;
+};
+
+#endif // QMLXMLPARSER_P_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/script/generator/generator.pro b/src/declarative/qml/script/generator/generator.pro
new file mode 100644
index 0000000..1b2a4c7
--- /dev/null
+++ b/src/declarative/qml/script/generator/generator.pro
@@ -0,0 +1,11 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Mon Apr 2 20:15:52 2007
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/src/declarative/qml/script/generator/main.cpp b/src/declarative/qml/script/generator/main.cpp
new file mode 100644
index 0000000..676671f
--- /dev/null
+++ b/src/declarative/qml/script/generator/main.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QList>
+#include <QByteArray>
+
+
+QT_BEGIN_NAMESPACE
+struct Keyword {
+ const char *lexem;
+ const char *token;
+};
+
+struct State
+{
+ State(const char* token) : token(token)
+ {
+ ::memset(next, 0, sizeof(next));
+ }
+ State(const State &other) : token(other.token)
+ {
+ ::memcpy(next, other.next, sizeof(next));
+ }
+ State &operator=(const State &other)
+ {
+ token = other.token;
+ ::memcpy(next, other.next, sizeof(next));
+ return *this;
+ }
+
+ QByteArray token;
+ int next[128];
+};
+
+Keyword keywords[] =
+{
+ {"<", "LANGLE" },
+ {">", "RANGLE" },
+ {"+", "PLUS" },
+ {"-", "MINUS" },
+ {"*", "STAR" },
+ {"==", "EQUALS" },
+ {"&&", "AND" },
+ {".", "DOT"},
+ {"true", "TOKEN_TRUE"},
+ {"false", "TOKEN_FALSE"},
+ {" ", "WHITESPACE"},
+ {"\t", "WHITESPACE"},
+ {0, 0}
+};
+
+bool is_character(char s)
+{
+ return (s >= 'a' && s <= 'z') ||
+ (s >= 'A' && s <= 'Z') ||
+ (s >= '0' && s <= '9') ||
+ s == '_';
+}
+
+void newState(QList<State> &states, const char *token, const char *lexem)
+{
+ int state = 0;
+ bool character = is_character(*lexem);
+
+ while(*lexem) {
+ int next = states[state].next[(int)*lexem];
+
+ if(!next) {
+ next = states.size();
+ states += State(character?"CHARACTER":"INCOMPLETE");
+ states[state].next[(int)*lexem] = next;
+ }
+
+ state = next;
+ ++lexem;
+ character = character && is_character(*lexem);
+ }
+
+ states[state].token = token;
+}
+
+void newState(QList<State> &states, const char *token, char lexem)
+{
+ int next = states[0].next[(int)lexem];
+ if(!next) {
+ next = states.size();
+ states += State(token);
+ states[0].next[(int)lexem] = next;
+ } else {
+ states[next].token = token;
+ }
+}
+
+int main()
+{
+ QList<State> states;
+ states += State("NOTOKEN");
+
+ // identifiers
+ for (int cc = 'a'; cc <= 'z'; ++cc)
+ newState(states, "CHARACTER", cc);
+ for (int cc = 'A'; cc <= 'Z'; ++cc)
+ newState(states, "CHARACTER", cc);
+ newState(states, "CHARACTER", '_');
+
+ // add digits
+ for(int cc = '0'; cc <= '9'; ++cc)
+ newState(states, "DIGIT", cc);
+
+ // keywords
+ for(int ii = 0; keywords[ii].lexem; ++ii)
+ newState(states, keywords[ii].token, keywords[ii].lexem);
+
+ ::printf("static const struct\n{\n"
+ " Token token;\n"
+ " char next[128];\n"
+ "} keywords[] = {\n");
+
+ for(int ii = 0; ii < states.size(); ++ii) {
+ printf("%s { %s, { ", ii?",\n":"", states[ii].token.data());
+ for(int jj = 0; jj < 128; jj++)
+ printf("%s%d", jj?",":"", states[ii].next[jj]);
+ printf(" } }");
+ }
+
+ printf("\n};\n");
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/instructions.h b/src/declarative/qml/script/instructions.h
new file mode 100644
index 0000000..a21cbce
--- /dev/null
+++ b/src/declarative/qml/script/instructions.h
@@ -0,0 +1,32 @@
+#ifndef _INSTRUCTIONS_H_
+#define _INSTRUCTIONS_H_
+
+struct ScriptInstruction {
+ enum {
+ Load, // fetch
+ Fetch, // fetch
+
+ Add, // NA
+ Subtract, // NA
+ Multiply, // NA
+ Equals, // NA
+ And, // NA
+
+ Int, // integer
+ Bool, // boolean
+ } type;
+
+ union {
+ struct {
+ int idx;
+ } fetch;
+ struct {
+ int value;
+ } integer;
+ struct {
+ bool value;
+ } boolean;
+ };
+};
+
+#endif // _INSTRUCTIONS_H_
diff --git a/src/declarative/qml/script/keywords.cpp b/src/declarative/qml/script/keywords.cpp
new file mode 100644
index 0000000..4cde65b
--- /dev/null
+++ b/src/declarative/qml/script/keywords.cpp
@@ -0,0 +1,89 @@
+static const struct
+{
+ Token token;
+ char next[128];
+} keywords[] = {
+ { NOTOKEN, { 0,0,0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,0,0,0,0,0,71,0,0,0,68,66,0,67,73,0,54,55,56,57,58,59,60,61,62,63,0,0,64,69,65,0,0,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,0,0,0,0,53,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DIGIT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { LANGLE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { RANGLE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { PLUS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { MINUS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { STAR, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { INCOMPLETE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { EQUALS, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { INCOMPLETE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { AND, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { DOT, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { TOKEN_TRUE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,79,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { CHARACTER, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { TOKEN_FALSE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { WHITESPACE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } },
+ { WHITESPACE, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }
+};
diff --git a/src/declarative/qml/script/lexer.cpp b/src/declarative/qml/script/lexer.cpp
new file mode 100644
index 0000000..d3ef935
--- /dev/null
+++ b/src/declarative/qml/script/lexer.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QByteArray>
+#include "lexer.h"
+#include "keywords.cpp"
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+QList<LexerToken> tokenize(const char *text)
+{
+ QList<LexerToken> rv;
+
+ int lineNo = 0;
+ int charNo = 0;
+ int state = 0;
+ int tokenStart = 0;
+ bool other = false;
+
+ const char *textprog = text;
+
+ bool done = false;
+ while (!done) {
+ char textchar = *textprog;
+ done = !textchar;
+
+ if (other) {
+ if (keywords[state].next[(int)textchar]) {
+
+ // Do other token
+ LexerToken token;
+ token.token = OTHER;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ other = false;
+
+ } else {
+ goto continue_loop;
+ }
+ }
+
+ if (keywords[state].next[(int)textchar]) {
+
+ state = keywords[state].next[(int)textchar];
+
+ } else if (0 == state ||
+ keywords[state].token == INCOMPLETE) {
+
+ other = true;
+ if (keywords[state].token == INCOMPLETE) {
+ state = 0;
+ continue;
+ }
+
+ } else {
+
+ // Token completed
+ Token tokenType = keywords[state].token;
+ bool tokenCollapsed = false;
+ if (tokenType == CHARACTER ||
+ tokenType == DIGIT ||
+ tokenType == WHITESPACE) {
+
+ Token lastTokenType =
+ rv.isEmpty()?NOTOKEN:rv.last().token;
+ if (tokenType == lastTokenType) {
+
+ rv.last().end = textprog - text - 1;
+ tokenStart = rv.last().end + 1;
+
+ tokenCollapsed = true;
+ }
+ }
+
+ if (!tokenCollapsed) {
+ LexerToken token;
+ token.token = keywords[state].token;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ }
+
+ state = keywords[0].next[(int)textchar];
+ if (0 == state)
+ other = true;
+ }
+
+continue_loop:
+ // Reset error reporting variables
+ if (textchar == '\n') {
+ ++lineNo;
+ charNo = 0;
+ } else {
+ charNo++;
+ }
+
+ // Increment ptrs
+ ++textprog;
+ }
+
+ if (other && ((textprog - text - 1) != tokenStart)) {
+ // Do other token
+ LexerToken token;
+ token.token = OTHER;
+ token.start = tokenStart;
+ token.end = textprog - text - 1;
+ token.line = lineNo + 1;
+ token.offset = charNo - (token.end - token.start);
+ tokenStart = token.end + 1;
+ rv.append(token);
+ other = false;
+ }
+ return rv;
+}
+
+void dumpTokens(const char *text, const QList<LexerToken> &tokens)
+{
+ for (int ii = 0; ii < tokens.count(); ++ii) {
+ QByteArray ba(text + tokens.at(ii).start, tokens.at(ii).end - tokens.at(ii).start + 1);
+ qWarning() << tokens.at(ii).line << ":" << tokens.at(ii).offset << tokenToString(tokens.at(ii).token) << "(" << tokens.at(ii).start << "-" << tokens.at(ii).end << ")" << ba;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/lexer.h b/src/declarative/qml/script/lexer.h
new file mode 100644
index 0000000..7781ee8
--- /dev/null
+++ b/src/declarative/qml/script/lexer.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include <QList>
+#include "tokens.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+struct LexerToken
+{
+ LexerToken() : token(NOTOKEN), start(-1), end(-1), line(-1), offset(-1) {}
+ LexerToken(const LexerToken &other) : token(other.token),
+ start(other.start),
+ end(other.end),
+ line(other.line),
+ offset(other.offset) {}
+ LexerToken &operator=(const LexerToken &other) {
+ token = other.token;
+ start = other.start;
+ end = other.end;
+ line = other.line;
+ offset = other.offset;
+ return *this;
+ }
+
+ Token token;
+ int start;
+ int end;
+ int line;
+ int offset;
+};
+
+QList<LexerToken> tokenize(const char *text);
+void dumpTokens(const char *text, const QList<LexerToken> &tokens);
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/qml/script/qmlbasicscript.cpp b/src/declarative/qml/script/qmlbasicscript.cpp
new file mode 100644
index 0000000..4f40016
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript.cpp
@@ -0,0 +1,923 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlbasicscript.h"
+#include "qmlbasicscript_p.h"
+#include "lexer.h"
+#include <QColor>
+#include <QDebug>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <QStack>
+#include <qfxperf.h>
+#include <private/qmlrefcount_p.h>
+
+
+QT_BEGIN_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
+
+class QmlBasicScriptPrivate
+{
+public:
+ enum Flags { OwnData = 0x00000001 };
+
+ int size;
+ int stateSize;
+ int instructionCount;
+ int exprLen;
+
+ ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); }
+
+ const char *expr() const
+ {
+ return (const char *)(instructions() + instructionCount);
+ }
+
+ const char *data() const
+ {
+ return (const char *)(instructions() + instructionCount) + exprLen + 1;
+ }
+
+ static unsigned int alignRound(int s)
+ {
+ if(s % 4)
+ s += 4 - (s % 4);
+ return s;
+ }
+};
+
+QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs)
+{
+ switch(rhs.type) {
+ case QmlBasicScriptNodeCache::Invalid:
+ lhs << "Invalid";
+ break;
+ case QmlBasicScriptNodeCache::Core:
+ lhs << "Core" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Attached:
+ lhs << "Attached" << rhs.object << rhs.attached;
+ break;
+ case QmlBasicScriptNodeCache::Signal:
+ lhs << "Signal" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::SignalProperty:
+ lhs << "SignalProperty" << rhs.object << rhs.core;
+ break;
+ case QmlBasicScriptNodeCache::Explicit:
+ lhs << "Explicit" << rhs.object;
+ break;
+ case QmlBasicScriptNodeCache::Variant:
+ lhs << "Variant" << rhs.context;
+ break;
+ case QmlBasicScriptNodeCache::ScriptValue:
+ lhs << "ScriptValue" << rhs.context;
+ break;
+ }
+
+ return lhs;
+}
+
+void QmlBasicScriptNodeCache::clear()
+{
+ object = 0;
+ metaObject = 0;
+ type = Invalid;
+}
+
+static QVariant toObjectOrVariant(const QVariant &v)
+{
+ switch(v.type()) {
+ case QVariant::String:
+ case QVariant::UInt:
+ case QVariant::Int:
+ case 135:
+ case QVariant::Double:
+ case QVariant::Color:
+ case QVariant::Bool:
+ default:
+ return v;
+ case QVariant::UserType:
+ {
+ QObject *o = QmlMetaType::toQObject(v);
+ if (o)
+ return qVariantFromValue(o);
+ else
+ return v;
+ }
+ break;
+ }
+}
+
+static QVariant fetch_value(QObject *o, int idx, int type)
+{
+ switch(type) {
+ case QVariant::String:
+ {
+ QString val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ uint val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Int:
+ {
+ int val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case 135:
+ case QVariant::Double:
+ {
+ qreal val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ default:
+ {
+ if(QmlMetaType::isObject(type)) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *val = 0;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant::fromValue(val);
+ } else {
+ QVariant var = o->metaObject()->property(idx).read(o);
+ if(QmlMetaType::isObject(var.userType())) {
+ QObject *obj = 0;
+ obj = *(QObject **)var.data();
+ var = QVariant::fromValue(obj);
+ }
+ return var;
+ }
+ }
+ break;
+ };
+}
+
+QVariant QmlBasicScriptNodeCache::value(const char *name) const
+{
+ //QFxPerfTimer<QFxPerf::BasicScriptValue> pt;
+ switch(type) {
+ case Invalid:
+ break;
+ case Core:
+ return fetch_value(object, core, coreType);
+ break;
+ case Attached:
+ return qVariantFromValue(static_cast<QObject *>(attached));
+ break;
+ case Signal:
+ // XXX
+ Q_ASSERT(!"Not implemented");
+ break;
+ case SignalProperty:
+ break;
+ case Explicit:
+ return qVariantFromValue(object);
+ break;
+ case Variant:
+ return toObjectOrVariant(context->variantProperties[QLatin1String(name)]);
+ break;
+ case ScriptValue:
+ return qVariantFromValue(context->properties[QLatin1String(name)]);
+ break;
+ };
+ return QVariant();
+}
+
+struct QmlBasicScriptCompiler
+{
+ QmlBasicScriptCompiler()
+ : script(0), stateSize(0), src(0), idx(0) {}
+ QmlBasicScript *script;
+ QList<LexerToken> tokens;
+ int stateSize;
+ const char *src;
+ int idx;
+
+ bool compile();
+ bool compileExpr();
+
+ bool parseFetch();
+ bool parseName();
+ bool parseConstant();
+ void skipWhitespace();
+
+ QByteArray data;
+ QList<ScriptInstruction> bytecode;
+
+ QByteArray string(int, int);
+ Token token() const;
+ bool atEnd() const;
+ void adv();
+ int index() const;
+};
+
+/*!
+ \class QmlBasicScript
+ \brief The QmlBasicScript class provides a fast implementation of a limited subset of JavaScript bindings.
+
+ QmlBasicScript instances are used to accelerate binding. Instead of using
+ the slower, fully fledged JavaScript engine, many simple bindings can be
+ evaluated using the QmlBasicScript engine.
+
+ To see if the QmlBasicScript engine can handle a binding, call compile()
+ and check the return value, or isValid() afterwards.
+
+ To evaluate the binding, the QmlBasicScript instance needs some memory in
+ which to cache state. This may be allocated by calling newScriptState()
+ and destroyed by calling deleteScriptState(). The state data is then passed
+ to the run() method when evaluating the binding.
+
+ To further accelerate binding, QmlBasicScript can return a precompiled
+ version of itself that can be saved for future use. Call compileData() to
+ get an opaque pointer to the compiled state, and compileDataSize() for the
+ size of this data in bytes. This data can be saved and passed to future
+ instances of the QmlBasicScript constructor. The initial copy of compile
+ data is owned by the QmlBindScript instance on which compile() was called.
+*/
+
+/*!
+ Create a new QmlBasicScript instance.
+*/
+QmlBasicScript::QmlBasicScript()
+: flags(0), d(0), rc(0)
+{
+}
+
+/*!
+ Create a new QmlBasicScript instance from saved \a data.
+
+ \a data \b must be data previously acquired from calling compileData() on a
+ previously created QmlBasicScript instance. Any other data will almost
+ certainly cause the QmlBasicScript engine to crash.
+
+ \a data must continue to be valid throughout the QmlBasicScript instance
+ life. It does not assume ownership of the memory.
+
+ If \a owner is set, it is referenced on creation and dereferenced on
+ destruction of this instance.
+*/
+QmlBasicScript::QmlBasicScript(const char *data, QmlRefCount *owner)
+: flags(0), d((QmlBasicScriptPrivate *)data), rc(owner)
+{
+ if(rc) rc->addref();
+}
+
+/*!
+ Return the text of the script expression.
+ */
+QByteArray QmlBasicScript::expression() const
+{
+ if(!d)
+ return QByteArray();
+ else
+ return QByteArray(d->expr());
+}
+
+/*!
+ Destroy the script instance.
+*/
+QmlBasicScript::~QmlBasicScript()
+{
+ if(flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if(rc) rc->release();
+ d = 0;
+ rc = 0;
+}
+
+/*!
+ Clear this script. The object will then be in its initial state, as though
+ it were freshly constructed with default constructor.
+*/
+void QmlBasicScript::clear()
+{
+ if(flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if(rc) rc->release();
+ d = 0;
+ rc = 0;
+ flags = 0;
+}
+
+/*!
+ Return the script state memory for this script instance. This memory should
+ only be destroyed by calling deleteScriptState().
+ */
+void *QmlBasicScript::newScriptState()
+{
+ if(!d) {
+ return 0;
+ } else {
+ void *rv = ::malloc(d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ ::memset(rv, 0, d->stateSize * sizeof(QmlBasicScriptNodeCache));
+ return rv;
+ }
+}
+
+/*!
+ Delete the \a data previously allocated by newScriptState().
+ */
+void QmlBasicScript::deleteScriptState(void *data)
+{
+ if(!data) return;
+ Q_ASSERT(d);
+ clearCache(data);
+ free(data);
+}
+
+/*!
+ Dump the script instructions to stderr for debugging.
+ */
+void QmlBasicScript::dump()
+{
+ if(!d)
+ return;
+
+ qWarning() << d->instructionCount << "instructions:";
+ const char *data = d->data();
+ for(int ii = 0; ii < d->instructionCount; ++ii) {
+ const ScriptInstruction &instr = d->instructions()[ii];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load:
+ qWarning().nospace() << "LOAD\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Fetch:
+ qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t"
+ << QByteArray(data + instr.fetch.idx);
+ break;
+ case ScriptInstruction::Add:
+ qWarning().nospace() << "ADD";
+ break;
+ case ScriptInstruction::Subtract:
+ qWarning().nospace() << "SUBTRACT";
+ break;
+ case ScriptInstruction::Multiply:
+ qWarning().nospace() << "MULTIPLY";
+ break;
+ case ScriptInstruction::Equals:
+ qWarning().nospace() << "EQUALS";
+ break;
+ case ScriptInstruction::Int:
+ qWarning().nospace() << "INT\t\t" << instr.integer.value;
+ break;
+ case ScriptInstruction::Bool:
+ qWarning().nospace() << "BOOL\t\t" << instr.boolean.value;
+ break;
+ default:
+ qWarning().nospace() << "UNKNOWN";
+ break;
+ }
+ }
+}
+
+/*!
+ Return true if this is a valid script binding, otherwise returns false.
+ */
+bool QmlBasicScript::isValid() const
+{
+ return d != 0;
+}
+
+/*!
+ Compile \a src and return true if the compilation is successful, otherwise
+ returns false.
+ */
+bool QmlBasicScript::compile(const QByteArray &src)
+{
+ bool rv = compile(src.constData());
+ return rv;
+}
+
+/*!
+ \overload
+
+ Compile \a src and return true if the compilation is successful, otherwise
+ returns false.
+ */
+bool QmlBasicScript::compile(const char *src)
+{
+ if(!src) return false;
+
+ QmlBasicScriptCompiler bsc;
+ bsc.script = this;
+ bsc.tokens = tokenize(src);
+ bsc.src = src;
+ // dumpTokens(src, bsc.tokens);
+
+ if(d) {
+ if(flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ d = 0;
+ flags = 0;
+ }
+
+ if(bsc.compile()) {
+ int len = ::strlen(src);
+ flags = QmlBasicScriptPrivate::OwnData;
+ int size = sizeof(QmlBasicScriptPrivate) +
+ bsc.bytecode.count() * sizeof(ScriptInstruction) +
+ QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1);
+ d = (QmlBasicScriptPrivate *) malloc(size);
+ d->size = size;
+ d->stateSize = bsc.stateSize;
+ d->instructionCount = bsc.bytecode.count();
+ d->exprLen = len;
+ ::memcpy((char *)d->expr(), src, len + 1);
+ for(int ii = 0; ii < d->instructionCount; ++ii)
+ d->instructions()[ii] = bsc.bytecode.at(ii);
+ ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count());
+ }
+
+ return d != 0;
+}
+
+void QmlBasicScriptCompiler::skipWhitespace()
+{
+ while(idx < tokens.count() && tokens.at(idx).token == WHITESPACE)
+ ++idx;
+}
+
+bool QmlBasicScriptCompiler::compile()
+{
+ if(!compileExpr())
+ return false;
+
+ skipWhitespace();
+
+ if(atEnd())
+ return true;
+
+ int t = token();
+ if(t != AND)
+ return false;
+
+ adv();
+ skipWhitespace();
+ if(!compileExpr())
+ return false;
+
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::And;
+ bytecode.append(instr);
+
+ skipWhitespace();
+
+ return atEnd();
+}
+
+bool QmlBasicScriptCompiler::compileExpr()
+{
+ /*
+ EXPRESSION := <NAME><OPERATOR>[<CONSTANT>|<NAME>]
+ */
+
+ if(!parseName())
+ return false;
+
+ skipWhitespace();
+
+ if(atEnd())
+ return true;
+
+ int t = token();
+ switch(t) {
+ case PLUS:
+ case MINUS:
+ /*
+ case LANGLE:
+ case RANGLE:
+ */
+ case STAR:
+ case EQUALS:
+ break;
+ default:
+ return true;
+ }
+ adv();
+
+ skipWhitespace();
+
+ if(!parseConstant() &&
+ !parseName())
+ return false;
+
+ ScriptInstruction instr;
+ switch(t) {
+ case PLUS:
+ instr.type = ScriptInstruction::Add;
+ break;
+ case MINUS:
+ instr.type = ScriptInstruction::Subtract;
+ break;
+ case STAR:
+ instr.type = ScriptInstruction::Multiply;
+ break;
+ case EQUALS:
+ instr.type = ScriptInstruction::Equals;
+ break;
+ default:
+ break;
+ }
+ bytecode.append(instr);
+
+ skipWhitespace();
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::parseName()
+{
+ skipWhitespace();
+
+ bool named = false;
+ bool seenchar = false;
+ bool seendot = false;
+ int namestart = -1;
+ bool pushed = false;
+ while(!atEnd()) {
+ int t = token();
+ if(t == CHARACTER) {
+ named = true;
+ seendot = false;
+ seenchar = true;
+ namestart = index();
+ adv();
+ } else if(t == DIGIT) {
+ if(!seenchar) break;
+ adv();
+ } else if(t == DOT) {
+ seendot = true;
+ if(namestart == -1)
+ break;
+
+ seenchar = false;
+ QByteArray name = string(namestart, index() - 1);
+ int nref = data.count();
+ data.append(name);
+ data.append('\0');
+ ScriptInstruction instr;
+ if(pushed)
+ instr.type = ScriptInstruction::Fetch;
+ else
+ instr.type = ScriptInstruction::Load;
+ pushed = true;
+ instr.fetch.idx = nref;
+ bytecode.append(instr);
+ ++stateSize;
+ namestart = -1;
+ adv();
+ } else {
+ break;
+ }
+ }
+
+ if(namestart != -1) {
+ QByteArray name = string(namestart, index() - 1);
+ int nref = data.count();
+ data.append(name);
+ data.append('\0');
+ ScriptInstruction instr;
+ if(pushed)
+ instr.type = ScriptInstruction::Fetch;
+ else
+ instr.type = ScriptInstruction::Load;
+ pushed = true;
+ instr.fetch.idx = nref;
+ bytecode.append(instr);
+ ++stateSize;
+ }
+
+ if(seendot)
+ return false;
+ else
+ return named;
+}
+
+bool QmlBasicScriptCompiler::parseConstant()
+{
+ switch(token()) {
+ case DIGIT:
+ {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::Int;
+ instr.integer.value = string(index(), index()).toUInt();
+ bytecode.append(instr);
+ adv();
+ }
+ break;
+ case TOKEN_TRUE:
+ case TOKEN_FALSE:
+ {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::Bool;
+ instr.boolean.value = (token() == TOKEN_TRUE);
+ bytecode.append(instr);
+ adv();
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::atEnd() const
+{
+ return idx >= tokens.count();
+}
+
+Token QmlBasicScriptCompiler::token() const
+{
+ return tokens.at(idx).token;
+}
+
+void QmlBasicScriptCompiler::adv()
+{
+ ++idx;
+}
+
+int QmlBasicScriptCompiler::index() const
+{
+ return idx;
+}
+
+QByteArray QmlBasicScriptCompiler::string(int from, int to)
+{
+ QByteArray rv;
+ for(int ii = from; ii <= to; ++ii) {
+ const LexerToken &token = tokens.at(ii);
+ rv.append(QByteArray(src + token.start, token.end - token.start + 1));
+ }
+ return rv;
+}
+
+/*!
+ \internal
+*/
+void QmlBasicScript::clearCache(void *voidCache)
+{
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+
+ for(int ii = 0; ii < d->stateSize; ++ii) {
+ if(!dataCache[ii].isCore() && !dataCache[ii].isExplicit() &&
+ dataCache[ii].object) {
+ QMetaObject::removeGuard(&dataCache[ii].object);
+ dataCache[ii].object = 0;
+ }
+ dataCache[ii].clear();
+ }
+}
+
+void QmlBasicScript::guard(QmlBasicScriptNodeCache &n)
+{
+ if(n.object) {
+ if(n.isExplicit()) {
+ } else if(n.isCore()) {
+ n.metaObject =
+ n.object->metaObject();
+ } else {
+ QMetaObject::addGuard(&n.object);
+ }
+ }
+}
+
+bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj)
+{
+ return n.object == obj &&
+ (!n.isCore() || obj->metaObject() == n.metaObject);
+}
+
+
+/*!
+ \enum QmlBasicScript::CacheState
+ \value NoChange The query has not change. Any previous monitoring is still
+ valid.
+ \value Incremental The query has been incrementally changed. Any previous
+ monitoring is still valid, but needs to have the fresh properties added to
+ it.
+ \value Reset The entire query has been reset from the beginning. Any previous
+ monitoring is now invalid.
+*/
+
+/*!
+ Run the script in \a context and return the result. \a voidCache should
+ contain state memory previously acquired from newScript.
+ */
+QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached)
+{
+ if(!isValid())
+ return QVariant();
+
+ QmlBasicScriptNodeCache *dataCache =
+ reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
+ int dataCacheItem;
+ QStack<QVariant> stack;
+
+ bool resetting = false;
+ bool hasReset = false;
+
+ const char *data = d->data();
+
+ if(dataCache[0].type == QmlBasicScriptNodeCache::Invalid) {
+ resetting = true;
+ hasReset = true;
+ }
+
+ CacheState state = NoChange;
+
+ dataCacheItem = 0;
+ for(int idx = 0; idx < d->instructionCount; ++idx) {
+ const ScriptInstruction &instr = d->instructions()[idx];
+
+ switch(instr.type) {
+ case ScriptInstruction::Load: // either an object or a property
+ case ScriptInstruction::Fetch: // can only be a property
+ {
+ const char *id = data + instr.fetch.idx;
+ QmlBasicScriptNodeCache &n = dataCache[dataCacheItem];
+
+ if(instr.type == ScriptInstruction::Load) {
+
+ if(n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr));
+ state = Incremental;
+ }
+
+ } else { // instr.type == ScriptInstruction::Fetch
+
+ QVariant o = stack.pop();
+ QObject *obj = qvariant_cast<QObject *>(o);
+ if(!obj) {
+ if(n.type == QmlBasicScriptNodeCache::Invalid) {
+ if(scriptWarnings())
+ qWarning() << "QmlBasicScript: Unable to convert" << o;
+ *cached = state;
+ return QVariant();
+ } else {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+ } else if(n.type == QmlBasicScriptNodeCache::Invalid) {
+ context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj);
+ guard(n);
+ state = Incremental;
+ } else if(!valid(n, obj)) {
+ clearCache(dataCache);
+ *cached = Reset;
+ CacheState dummy;
+ return run(context, voidCache, &dummy);
+ }
+
+ }
+
+ QVariant var = n.value(id);
+ stack.push(var);
+ ++dataCacheItem;
+ }
+ break;
+ case ScriptInstruction::Int:
+ stack.push(QVariant(instr.integer.value));
+ break;
+ case ScriptInstruction::Bool:
+ stack.push(QVariant(instr.boolean.value));
+ break;
+ case ScriptInstruction::Add:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() + lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Subtract:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(lhs.toDouble() - rhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Multiply:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toDouble() * lhs.toDouble());
+ }
+ break;
+ case ScriptInstruction::Equals:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs == lhs);
+ }
+ break;
+ case ScriptInstruction::And:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs.toBool() && lhs.toBool());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ *cached = state;
+
+ if(stack.isEmpty())
+ return QVariant();
+ else
+ return stack.top();
+}
+
+/*!
+ Return a pointer to the script's compile data, or null if there is no data.
+ */
+const char *QmlBasicScript::compileData() const
+{
+ return (const char *)d;
+}
+
+/*!
+ Return the size of the script's compile data, or zero if there is no data.
+ The size will always be a multiple of 4.
+ */
+unsigned int QmlBasicScript::compileDataSize() const
+{
+ if(d)
+ return d->size;
+ else
+ return 0;
+}
+
+bool QmlBasicScript::isSingleLoad() const
+{
+ if(!d)
+ return false;
+
+ return d->instructionCount == 1 &&
+ d->instructions()[0].type == ScriptInstruction::Load;
+}
+
+QByteArray QmlBasicScript::singleLoadTarget() const
+{
+ if(!isSingleLoad())
+ return QByteArray();
+
+ // We know there is one instruction and it is a load
+ return QByteArray(d->data() + d->instructions()[0].fetch.idx);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/qmlbasicscript.h b/src/declarative/qml/script/qmlbasicscript.h
new file mode 100644
index 0000000..d465f04
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBASICSCRIPT_H
+#define QMLBASICSCRIPT_H
+
+#include "instructions.h"
+#include <QList>
+#include <QByteArray>
+#include "lexer.h"
+#include <QVariant>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+class QmlRefCount;
+class QmlContext;
+class QmlBasicScriptPrivate;
+class QmlBasicScriptNodeCache;
+class QmlBasicScript
+{
+public:
+ QmlBasicScript();
+ QmlBasicScript(const char *, QmlRefCount * = 0);
+ ~QmlBasicScript();
+
+ // Always 4-byte aligned
+ const char *compileData() const;
+ unsigned int compileDataSize() const;
+
+ QByteArray expression() const;
+
+ bool compile(const QByteArray &);
+ bool compile(const char *);
+ bool isValid() const;
+
+ void clear();
+
+ void dump();
+ void *newScriptState();
+ void deleteScriptState(void *);
+
+ enum CacheState { NoChange, Incremental, Reset };
+ QVariant run(QmlContext *, void *, CacheState *);
+
+ // Optimization opportunities
+ bool isSingleLoad() const;
+ QByteArray singleLoadTarget() const;
+
+private:
+ int flags;
+ QmlBasicScriptPrivate *d;
+ QmlRefCount *rc;
+
+ void clearCache(void *);
+ void guard(QmlBasicScriptNodeCache &);
+ bool valid(QmlBasicScriptNodeCache &, QObject *);
+};
+
+#endif // QMLBASICSCRIPT_H
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
diff --git a/src/declarative/qml/script/qmlbasicscript_p.h b/src/declarative/qml/script/qmlbasicscript_p.h
new file mode 100644
index 0000000..bcb7d00
--- /dev/null
+++ b/src/declarative/qml/script/qmlbasicscript_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLBASICSCRIPT_P_H
+#define QMLBASICSCRIPT_P_H
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QmlContextPrivate;
+class QDebug;
+class QByteArray;
+
+class QmlBasicScriptNodeCache
+{
+public:
+ QObject *object;
+ const QMetaObject *metaObject;
+ enum { Invalid,
+ Core,
+ Attached,
+ Signal,
+ SignalProperty,
+ Explicit,
+ Variant,
+ ScriptValue } type;
+ union {
+ int core;
+ QObject *attached;
+ QmlContextPrivate *context;
+ };
+ int coreType;
+
+ bool isCore() const { return type == Core; }
+ bool isExplicit() const { return type == Explicit; }
+ void clear();
+ QVariant value(const char *) const;
+};
+
+QDebug operator<<(QDebug, const QmlBasicScriptNodeCache &);
+
+#endif // QMLBASICSCRIPT_P_H
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/script/script.pri b/src/declarative/qml/script/script.pri
new file mode 100644
index 0000000..6c43efe
--- /dev/null
+++ b/src/declarative/qml/script/script.pri
@@ -0,0 +1,11 @@
+SOURCES += \
+ qml/script/tokens.cpp \
+ qml/script/lexer.cpp \
+ qml/script/qmlbasicscript.cpp
+
+HEADERS += \
+ qml/script/tokens.h \
+ qml/script/lexer.h \
+ qml/script/instructions.h \
+ qml/script/qmlbasicscript.h \
+ qml/script/qmlbasicscript_p.h
diff --git a/src/declarative/qml/script/tokens.cpp b/src/declarative/qml/script/tokens.cpp
new file mode 100644
index 0000000..51b46f0
--- /dev/null
+++ b/src/declarative/qml/script/tokens.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "tokens.h"
+
+
+/*!
+ \relates <tokens.h>
+ Returns a string representation of token \a tok.
+*/
+const char *tokenToString(Token tok)
+{
+ switch(tok) {
+#define CASE(X) case X: return #X;
+ CASE(NOTOKEN)
+ CASE(INCOMPLETE)
+ CASE(WHITESPACE)
+ CASE(LANGLE)
+ CASE(RANGLE)
+ CASE(PLUS)
+ CASE(MINUS)
+ CASE(STAR)
+ CASE(EQUALS)
+ CASE(DOT)
+ CASE(CHARACTER)
+ CASE(DIGIT)
+ CASE(OTHER)
+ CASE(AND)
+ case TOKEN_TRUE:
+ return "TRUE";
+ case TOKEN_FALSE:
+ return "FALSE";
+#undef CASE
+ }
+ return 0;
+}
+
diff --git a/src/declarative/qml/script/tokens.h b/src/declarative/qml/script/tokens.h
new file mode 100644
index 0000000..753e40c
--- /dev/null
+++ b/src/declarative/qml/script/tokens.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENS_H
+#define TOKENS_H
+
+enum Token {
+ // Lexer tokens
+ NOTOKEN,
+ INCOMPLETE,
+ WHITESPACE,
+ LANGLE,
+ RANGLE,
+ PLUS,
+ MINUS,
+ STAR,
+ EQUALS,
+ AND,
+ DOT,
+ CHARACTER,
+ DIGIT,
+ TOKEN_TRUE,
+ TOKEN_FALSE,
+ OTHER
+};
+
+const char *tokenToString(Token);
+
+#endif