From 6207a3a04080f1d4423a50c4b2a2aeb93052a392 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 25 Sep 2009 17:15:19 +1000 Subject: Prototype a QScriptDeclarativeClass that fits better with qml --- src/script/bridge/bridge.pri | 8 +- src/script/bridge/qscriptdeclarativeclass.cpp | 221 +++++++++++++++++++++++++ src/script/bridge/qscriptdeclarativeclass_p.h | 127 ++++++++++++++ src/script/bridge/qscriptdeclarativeobject.cpp | 186 +++++++++++++++++++++ src/script/bridge/qscriptdeclarativeobject_p.h | 110 ++++++++++++ src/script/bridge/qscriptobject_p.h | 3 +- 6 files changed, 652 insertions(+), 3 deletions(-) create mode 100644 src/script/bridge/qscriptdeclarativeclass.cpp create mode 100644 src/script/bridge/qscriptdeclarativeclass_p.h create mode 100644 src/script/bridge/qscriptdeclarativeobject.cpp create mode 100644 src/script/bridge/qscriptdeclarativeobject_p.h diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri index 666a07e..09e2dfb 100644 --- a/src/script/bridge/bridge.pri +++ b/src/script/bridge/bridge.pri @@ -5,7 +5,9 @@ SOURCES += \ $$PWD/qscriptvariant.cpp \ $$PWD/qscriptqobject.cpp \ $$PWD/qscriptglobalobject.cpp \ - $$PWD/qscriptactivationobject.cpp + $$PWD/qscriptactivationobject.cpp \ + $$PWD/qscriptdeclarativeobject.cpp \ + $$PWD/qscriptdeclarativeclass.cpp HEADERS += \ $$PWD/qscriptfunction_p.h \ @@ -14,4 +16,6 @@ HEADERS += \ $$PWD/qscriptvariant_p.h \ $$PWD/qscriptqobject_p.h \ $$PWD/qscriptglobalobject_p.h \ - $$PWD/qscriptactivationobject_p.h + $$PWD/qscriptactivationobject_p.h \ + $$PWD/qscriptdeclarativeobject_p.h \ + $$PWD/qscriptdeclarativeclass_p.h diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp new file mode 100644 index 0000000..47b693f --- /dev/null +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qscriptdeclarativeclass_p.h" +#include "qscriptdeclarativeobject_p.h" +#include "qscriptobject_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QScriptDeclarativeClassPrivate +{ +public: + QScriptDeclarativeClassPrivate() {} + + QScriptEngine *engine; + QScriptDeclarativeClass *q_ptr; +}; + +void QScriptDeclarativeClass::destroyPersistentIdentifier(void **d) +{ + ((JSC::Identifier *)d)->JSC::Identifier::~Identifier(); +} + +void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, const QString &str) +{ + QScriptEnginePrivate *p = + static_cast(QObjectPrivate::get(d_ptr->engine)); + JSC::ExecState* exec = p->currentFrame; + + new (*d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); + *i = (Identifier)((JSC::Identifier *)*d)->ustring().rep(); +} + +void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, const Identifier &id) +{ + QScriptEnginePrivate *p = + static_cast(QObjectPrivate::get(d_ptr->engine)); + JSC::ExecState* exec = p->currentFrame; + + new (*d) JSC::Identifier(exec, (JSC::UString::Rep *)id); + *i = id; +} + +QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) +: d_ptr(new QScriptDeclarativeClassPrivate) +{ + Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier)); + d_ptr->q_ptr = this; + d_ptr->engine = engine; +} + +QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine, + QScriptDeclarativeClass *scriptClass, + Object object) +{ + Q_ASSERT(engine); + Q_ASSERT(scriptClass); + + QScriptEnginePrivate *p = static_cast(QObjectPrivate::get(engine)); + + JSC::ExecState* exec = p->currentFrame; + QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure); + result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object)); + return p->scriptValueFromJSCValue(result); +} + +QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return 0; + QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return 0; + return static_cast(delegate)->scriptClass(); +} + +QScriptDeclarativeClass::Object QScriptDeclarativeClass::object(const QScriptValue &v) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return 0; + QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return 0; + return static_cast(delegate)->object(); +} + +QScriptDeclarativeClass::~QScriptDeclarativeClass() +{ +} + +QScriptEngine *QScriptDeclarativeClass::engine() const +{ + return d_ptr->engine; +} + +/* +QScriptDeclarativeClass::PersistentIdentifier * +QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) +{ + QScriptEnginePrivate *p = + static_cast(QObjectPrivate::get(d_ptr->engine)); + JSC::ExecState* exec = p->currentFrame; + + PersistentIdentifierPrivate *rv = new PersistentIdentifierPrivate; + rv->identifierValue = JSC::Identifier(exec, (UChar *)str.constData(), str.size()); + rv->identifier = (void *)rv->identifierValue.ustring().rep(); + return rv; +} + +QScriptDeclarativeClass::PersistentIdentifier * +QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id) +{ + QScriptEnginePrivate *p = + static_cast(QObjectPrivate::get(d_ptr->engine)); + JSC::ExecState* exec = p->currentFrame; + + PersistentIdentifierPrivate *rv = new PersistentIdentifierPrivate; + rv->identifierValue = JSC::Identifier(exec, (JSC::UString::Rep *)id); + rv->identifier = (void *)rv->identifierValue.ustring().rep(); + return rv; +} +*/ + + +QString QScriptDeclarativeClass::toString(const Identifier &identifier) +{ + JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; + return QString((QChar *)r->data(), r->size()); +} + +QScriptClass::QueryFlags +QScriptDeclarativeClass::queryProperty(const Object &object, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(object); + Q_UNUSED(name); + Q_UNUSED(flags); + return 0; +} + +QScriptValue QScriptDeclarativeClass::property(const Object &object, const Identifier &name) +{ + Q_UNUSED(object); + Q_UNUSED(name); + return QScriptValue(); +} + +void QScriptDeclarativeClass::setProperty(const Object &object, const Identifier &name, + const QScriptValue &value) +{ + Q_UNUSED(object); + Q_UNUSED(name); + Q_UNUSED(value); +} + +QScriptValue::PropertyFlags +QScriptDeclarativeClass::propertyFlags(const Object &object, const Identifier &name) +{ + Q_UNUSED(object); + Q_UNUSED(name); + return 0; +} + +QStringList QScriptDeclarativeClass::propertyNames(const Object &object) +{ + Q_UNUSED(object); + return QStringList(); +} + +void QScriptDeclarativeClass::destroyed(const Object &object) +{ + Q_UNUSED(object); +} + diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h new file mode 100644 index 0000000..5705a51 --- /dev/null +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTDECLARATIVECLASS_P_H +#define QSCRIPTDECLARATIVECLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QScriptDeclarativeClassPrivate; +class PersistentIdentifierPrivate; +class Q_SCRIPT_EXPORT QScriptDeclarativeClass +{ +public: + typedef void* Identifier; + typedef void* Object; + + static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object); + static QScriptDeclarativeClass *scriptClass(const QScriptValue &); + static Object object(const QScriptValue &); + + template + class PersistentIdentifier : public T { + public: + Identifier identifier; + + ~PersistentIdentifier() { QScriptDeclarativeClass::destroyPersistentIdentifier(&d); } + private: + friend class QScriptDeclarativeClass; + PersistentIdentifier() : identifier(0), d(0) {} + void *d; + }; + + QScriptDeclarativeClass(QScriptEngine *engine); + virtual ~QScriptDeclarativeClass(); + + QScriptEngine *engine() const; + + template + PersistentIdentifier *createPersistentIdentifier(const QString &str) { + PersistentIdentifier *rv = new PersistentIdentifier; + initPersistentIdentifier(&rv->d, &rv->identifier, str); + return rv; + } + template + PersistentIdentifier *createPersistentIdentifier(const Identifier &id) { + PersistentIdentifier *rv = new PersistentIdentifier; + initPersistentIdentifier(&rv->d, &rv->identifier, id); + return rv; + } + + QString toString(const Identifier &); + + virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + QScriptClass::QueryFlags flags); + + virtual QScriptValue property(const Object &, const Identifier &); + virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + virtual QScriptValue::PropertyFlags propertyFlags(const Object &, const Identifier &); + + virtual QStringList propertyNames(const Object &); + + virtual void destroyed(const Object &); + + static void destroyPersistentIdentifier(void **); + void initPersistentIdentifier(void **, Identifier *, const QString &); + void initPersistentIdentifier(void **, Identifier *, const Identifier &); + +protected: + QScopedPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp new file mode 100644 index 0000000..62c2686 --- /dev/null +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptdeclarativeobject_p.h" + +#include "../api/qscriptengine.h" +#include "../api/qscriptengine_p.h" +#include "../api/qscriptcontext.h" +#include "../api/qscriptcontext_p.h" +#include "../api/qscriptclass.h" +#include "../api/qscriptclasspropertyiterator.h" + +#include "Error.h" +#include "PropertyNameArray.h" + +#include + +Q_DECLARE_METATYPE(QScriptContext*) +Q_DECLARE_METATYPE(QScriptValue) +Q_DECLARE_METATYPE(QScriptValueList) + +QT_BEGIN_NAMESPACE + +namespace QScript +{ + +DeclarativeObjectDelegate::DeclarativeObjectDelegate(QScriptDeclarativeClass *c, + QScriptDeclarativeClass::Object &o) +: m_class(c), m_object(o) +{ +} + +DeclarativeObjectDelegate::~DeclarativeObjectDelegate() +{ + m_class->destroyed(m_object); +} + +QScriptObjectDelegate::Type DeclarativeObjectDelegate::type() const +{ + return DeclarativeClassObject; +} + +bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::PropertySlot &slot) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); + + QScriptClass::QueryFlags flags = + m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); + if (flags & QScriptClass::HandlesReadAccess) { + QScriptValue value = m_class->property(m_object, identifier); + slot.setValue(engine->scriptValueToJSCValue(value)); + return true; + } + + return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); +} + +void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::JSValue value, JSC::PutPropertySlot &slot) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); + + QScriptClass::QueryFlags flags = + m_class->queryProperty(m_object, identifier, QScriptClass::HandlesWriteAccess); + if (flags & QScriptClass::HandlesWriteAccess) { + m_class->setProperty(m_object, identifier, engine->scriptValueFromJSCValue(value)); + return; + } + QScriptObjectDelegate::put(object, exec, propertyName, value, slot); +} + +bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, + const JSC::Identifier &propertyName, + bool checkDontDelete) +{ + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); +} + +bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + unsigned &attribs) const +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); + + QScriptClass::QueryFlags flags = + m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); + if (flags & QScriptClass::HandlesReadAccess) { + QScriptValue::PropertyFlags flags = m_class->propertyFlags(m_object, identifier); + attribs = 0; + if (flags & QScriptValue::ReadOnly) + attribs |= JSC::ReadOnly; + if (flags & QScriptValue::SkipInEnumeration) + attribs |= JSC::DontEnum; + if (flags & QScriptValue::Undeletable) + attribs |= JSC::DontDelete; + if (flags & QScriptValue::PropertyGetter) + attribs |= JSC::Getter; + if (flags & QScriptValue::PropertySetter) + attribs |= JSC::Setter; + attribs |= flags & QScriptValue::UserRange; + return true; + } + return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); +} + +void DeclarativeObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + unsigned listedAttributes) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + + QStringList properties = m_class->propertyNames(m_object); + for (int ii = 0; ii < properties.count(); ++ii) { + const QString &name = properties.at(ii); + propertyNames.add(JSC::Identifier(exec, name)); + } + + QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); +} + +JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData) +{ + return QScriptObjectDelegate::getCallData(object, callData); +} + +JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData) +{ + return QScriptObjectDelegate::getConstructData(object, constructData); +} + +bool DeclarativeObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec, + JSC::JSValue value, JSC::JSValue proto) +{ + return QScriptObjectDelegate::hasInstance(object, exec, value, proto); +} + +} // namespace QScript + +QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h new file mode 100644 index 0000000..87375d8 --- /dev/null +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTDECLARATIVEOBJECT_P_H +#define QSCRIPTDECLARATIVEOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "qscriptobject_p.h" +#include "qscriptdeclarativeclass_p.h" + +QT_BEGIN_NAMESPACE + +class QScriptClass; + +namespace QScript +{ + +class DeclarativeObjectDelegate : public QScriptObjectDelegate +{ +public: + DeclarativeObjectDelegate(QScriptDeclarativeClass *c, QScriptDeclarativeClass::Object &o); + ~DeclarativeObjectDelegate(); + + virtual Type type() const; + + QScriptDeclarativeClass *scriptClass() const { return m_class; } + QScriptDeclarativeClass::Object object() const { return m_object; } + + virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + virtual void put(QScriptObject*, JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::JSValue, JSC::PutPropertySlot&); + virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + bool checkDontDelete = true); + virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, + const JSC::Identifier&, + unsigned&) const; + virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, + JSC::PropertyNameArray&, + unsigned listedAttributes = JSC::Structure::Prototype); + + virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); + virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); + + virtual bool hasInstance(QScriptObject*, JSC::ExecState*, + JSC::JSValue value, JSC::JSValue proto); + +private: + QScriptDeclarativeClass *m_class; + QScriptDeclarativeClass::Object m_object; +}; + +} // namespace QScript + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h index c1cee31..a5858ac 100644 --- a/src/script/bridge/qscriptobject_p.h +++ b/src/script/bridge/qscriptobject_p.h @@ -127,7 +127,8 @@ public: enum Type { QtObject, Variant, - ClassObject + ClassObject, + DeclarativeClassObject }; QScriptObjectDelegate(); -- cgit v0.12 From f9f878ca1fff08b6ea24507a84adfeb16d8938b6 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 28 Sep 2009 18:51:54 +1000 Subject: Add two step compile/evaluate support to QScript --- src/script/api/qscriptengine.cpp | 173 +++++++++++++++++++++++++++++++++++++++ src/script/api/qscriptengine.h | 26 ++++++ 2 files changed, 199 insertions(+) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index fb14940..7256f27 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -340,6 +340,24 @@ public: JSC::JSValue prototype; }; +class QScriptProgramPrivate +{ +public: + QScriptProgramPrivate() : refcount(1), hasException(false) { } + + void addref() { ++refcount; } + void release() { if (--refcount) delete this; } + + int refcount; + + bool hasException; + QScriptValue exception; + + JSC::SourceCode source; + WTF::RefPtr evalNode; +}; + + namespace QScript { @@ -2114,7 +2132,112 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra return QScriptSyntaxCheckResult(p); } +QScriptProgram QScriptEngine::compile(const QString &program, const QString &fileName, int lineNumber) +{ + Q_D(QScriptEngine); + + QScriptProgram rv; + rv.d = new QScriptProgramPrivate; + + JSC::JSLock lock(false); // ### hmmm + QBoolBlocker inEval(d->inEval, true); + currentContext()->activationObject(); //force the creation of a context for native function; + + JSC::UString jscProgram = program; + JSC::UString jscFileName = fileName; + JSC::ExecState* exec = d->currentFrame; + + JSC::SourceCode &source = rv.d->source; + source = JSC::makeSource(jscProgram, jscFileName, lineNumber); + + intptr_t sourceId = source.provider()->asID(); + JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + if (debugger) + debugger->evaluateStart(sourceId); + + exec->clearException(); + JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject()); + + int errorLine; + JSC::UString errorMessage; + WTF::RefPtr &evalNode = rv.d->evalNode; + evalNode = exec->globalData().parser->parse(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage); + if (!evalNode) { + JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0); + exec->setException(exceptionValue); + + if (debugger) { + debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, exceptionValue), sourceId, false); + debugger->evaluateStop(exceptionValue, sourceId); + } + + rv.d->hasException = true; + rv.d->exception = d->scriptValueFromJSCValue(exceptionValue); + } else if (debugger) { + debugger->evaluateStop(JSC::JSValue(), sourceId); + } + + return rv; +} + +QScriptValue QScriptEngine::evaluate(const QScriptProgram &program) +{ + Q_D(QScriptEngine); + + if (0 == program.d) + return QScriptValue(); + else if (program.d->hasException) + return program.d->exception; + else if (!program.d->evalNode) + return QScriptValue(); + + JSC::JSLock lock(false); // ### hmmm + QBoolBlocker inEval(d->inEval, true); + currentContext()->activationObject(); //force the creation of a context for native function; + + JSC::ExecState* exec = d->currentFrame; + + intptr_t sourceId = program.d->source.provider()->asID(); + JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + if (debugger) + debugger->evaluateStart(sourceId); + + exec->clearException(); + JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject()); + + WTF::RefPtr &evalNode = program.d->evalNode; + + JSC::JSValue thisValue = d->thisForContext(exec); + JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); + JSC::JSValue exceptionValue; + d->timeoutChecker()->setShouldAbort(false); + JSC::JSValue result = exec->interpreter()->execute(evalNode.get(), exec, thisObject, exec->scopeChain(), &exceptionValue); + + if (d->timeoutChecker()->shouldAbort()) { + if (d->abortResult.isError()) + exec->setException(d->scriptValueToJSCValue(d->abortResult)); + if (debugger) + debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId); + + return d->abortResult; + } + + if (exceptionValue) { + exec->setException(exceptionValue); + + if (debugger) + debugger->evaluateStop(exceptionValue, sourceId); + + return d->scriptValueFromJSCValue(exceptionValue); + } + + if (debugger) + debugger->evaluateStop(result, sourceId); + + Q_ASSERT(!exec->hadException()); + return d->scriptValueFromJSCValue(result); +} /*! Evaluates \a program, using \a lineNumber as the base line number, @@ -3708,6 +3831,9 @@ QScriptValue QScriptEngine::objectById(qint64 id) const return const_cast(d)->scriptValueFromJSCValue((JSC::JSCell*)id); } + + + /*! \since 4.5 \class QScriptSyntaxCheckResult @@ -3836,4 +3962,51 @@ Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled() } #endif +QScriptProgram::QScriptProgram() +: d(0) +{ +} + +QScriptProgram::~QScriptProgram() +{ + if (d) d->release(); +} + +QScriptProgram::QScriptProgram(const QScriptProgram &c) +: d(c.d) +{ + if (d) d->addref(); +} + +QScriptProgram &QScriptProgram::operator=(const QScriptProgram &c) +{ + if (c.d) c.d->addref(); + if (d) d->release(); + d = c.d; + return *this; +} + +bool QScriptProgram::isNull() const +{ + return d == 0; +} + +bool QScriptProgram::hasSyntaxError() const +{ + if (d) return d->hasException; + else return false; +} + +QScriptValue QScriptProgram::syntaxError() const +{ + if (d) return d->exception; + else return QScriptValue(); +} + +QString QScriptProgram::programSource() const +{ + if (d) return d->source.toString(); + else return QString(); +} + QT_END_NAMESPACE diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 701f9c6..71266cc 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -120,6 +120,29 @@ private: friend class QScriptEnginePrivate; }; +class QScriptProgramPrivate; +class Q_SCRIPT_EXPORT QScriptProgram +{ +public: + QScriptProgram(); + QScriptProgram(const QScriptProgram &); + ~QScriptProgram(); + + QScriptProgram &operator=(const QScriptProgram &); + + bool isNull() const; + + bool hasSyntaxError() const; + QScriptValue syntaxError() const; + + QString programSource() const; + +private: + friend class QScriptEngine; + QScriptProgramPrivate *d; +}; + +class QScriptCode; class Q_SCRIPT_EXPORT QScriptEngine #ifndef QT_NO_QOBJECT : public QObject @@ -164,6 +187,9 @@ public: bool canEvaluate(const QString &program) const; static QScriptSyntaxCheckResult checkSyntax(const QString &program); + QScriptProgram compile(const QString &program, const QString &fileName = QString(), int lineNumber = 1); + QScriptValue evaluate(const QScriptProgram &); + QScriptValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); bool isEvaluating() const; -- cgit v0.12 From 061c85a17ecb303676b548e6daef6e64967ca1e7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 28 Sep 2009 21:21:25 +1000 Subject: Use QScriptProgram to speed up binding creation --- src/declarative/qml/qmlcompileddata.cpp | 2 ++ src/declarative/qml/qmlcompiler.cpp | 3 +++ src/declarative/qml/qmlcompiler_p.h | 6 +++--- src/declarative/qml/qmlexpression.cpp | 21 ++++++++++++++++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index b2e2d40..a46d893 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -159,6 +159,8 @@ QmlCompiledData::~QmlCompiledData() if (types.at(ii).ref) types.at(ii).ref->release(); } + + qDeleteAll(programs); } QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 02cd813..e67f79a 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2296,7 +2296,10 @@ bool QmlCompiler::completeComponentBuild() expression = rewriteBinding(expression); quint32 length = expression.length(); + quint32 pc = output->programs.length(); + output->programs.append(0); binding.compiledData = + QByteArray((const char *)&pc, sizeof(quint32)) + QByteArray((const char *)&length, sizeof(quint32)) + QByteArray((const char *)expression.constData(), expression.length() * sizeof(QChar)); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 00637e3..447c421 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -69,6 +69,7 @@ class QmlEngine; class QmlComponent; class QmlContext; +class QScriptProgram; class QmlCompiledData : public QmlRefCount { public: @@ -106,6 +107,7 @@ public: QList datas; QList locations; QList bytecode; + QList programs; void dumpInstructions(); private: @@ -253,12 +255,10 @@ private: struct ComponentCompileState { ComponentCompileState() - : parserStatusCount(0), savedObjects(0), - pushedProperties(0), root(0) {} + : parserStatusCount(0), pushedProperties(0), root(0) {} QHash ids; QHash idIndexes; int parserStatusCount; - int savedObjects; int pushedProperties; QHash bindings; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index db9d39f..adf5261 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -45,6 +45,7 @@ #include "qmlcontext_p.h" #include "qmlrewrite_p.h" #include "QtCore/qdebug.h" +#include "qmlcompiler_p.h" Q_DECLARE_METATYPE(QList); @@ -74,8 +75,26 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, if (*data == BasicScriptEngineData) { sse.load((const char *)(data + 1), rc); } else { - expression = QString::fromRawData((QChar *)(data + 2), data[1]); + QmlCompiledData *dd = (QmlCompiledData *)rc; + expressionRewritten = true; + expression = QString::fromRawData((QChar *)(data + 3), data[2]); + + int progIdx = *(data + 1); + QmlEngine *engine = ctxt->engine(); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + if (!dd->programs.at(progIdx)) { + dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(expression)); + } + + QmlContextPrivate *ctxtPriv = ctxt->d_func(); + QScriptContext *scriptContext = scriptEngine->pushContext(); + for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i) + scriptContext->pushScope(ctxtPriv->scopeChain.at(i)); + + expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); + expressionFunctionValid = true; + scriptEngine->popContext(); } QmlAbstractExpression::setContext(ctxt); -- cgit v0.12 From c4190288ca68eca9b84ccab67d860517a6a8e7c5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 29 Sep 2009 21:50:31 +1000 Subject: Use placement new correctly --- src/script/bridge/qscriptdeclarativeclass.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 47b693f..c753379 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -70,8 +70,8 @@ void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - new (*d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); - *i = (Identifier)((JSC::Identifier *)*d)->ustring().rep(); + new (d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); + *i = (Identifier)((JSC::Identifier *)d)->ustring().rep(); } void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, const Identifier &id) @@ -80,7 +80,7 @@ void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - new (*d) JSC::Identifier(exec, (JSC::UString::Rep *)id); + new (d) JSC::Identifier(exec, (JSC::UString::Rep *)id); *i = id; } -- cgit v0.12 From 49527e854a9edb0a92e64264d6efac6be46cf0ed Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 30 Sep 2009 11:07:07 +1000 Subject: Create a property cache for synthesized metaobjects --- src/declarative/qml/qml.pri | 6 +- src/declarative/qml/qmlcompileddata.cpp | 3 + src/declarative/qml/qmlcompiler.cpp | 6 +- src/declarative/qml/qmlcompiler_p.h | 3 + src/declarative/qml/qmldeclarativedata_p.h | 3 + src/declarative/qml/qmlengine.cpp | 14 ++- src/declarative/qml/qmlengine_p.h | 18 +++- src/declarative/qml/qmlinstruction.cpp | 2 +- src/declarative/qml/qmlinstruction_p.h | 2 +- src/declarative/qml/qmlmetaproperty.cpp | 71 +++------------ src/declarative/qml/qmlmetaproperty_p.h | 22 ----- src/declarative/qml/qmlpropertycache.cpp | 137 +++++++++++++++++++++++++++++ src/declarative/qml/qmlpropertycache_p.h | 100 +++++++++++++++++++++ src/declarative/qml/qmlvme.cpp | 9 +- 14 files changed, 303 insertions(+), 93 deletions(-) create mode 100644 src/declarative/qml/qmlpropertycache.cpp create mode 100644 src/declarative/qml/qmlpropertycache_p.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 8349e29..216adb1 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -34,7 +34,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlxmlhttprequest.cpp \ qml/qmlsqldatabase.cpp \ qml/qmetaobjectbuilder.cpp \ - qml/qmlwatcher.cpp + qml/qmlwatcher.cpp \ + qml/qmlpropertycache.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -86,7 +87,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlxmlhttprequest_p.h \ qml/qmlsqldatabase_p.h \ qml/qmetaobjectbuilder_p.h \ - qml/qmlwatcher_p.h + qml/qmlwatcher_p.h \ + qml/qmlpropertycache_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index a46d893..a603d4e 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -160,6 +160,9 @@ QmlCompiledData::~QmlCompiledData() types.at(ii).ref->release(); } + for (int ii = 0; ii < propertyCaches.count(); ++ii) + propertyCaches.at(ii)->release(); + qDeleteAll(programs); } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index e67f79a..0b4ac20 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -647,7 +647,7 @@ void QmlCompiler::compileTree(Object *tree) Q_ASSERT(tree->metatype); static_cast(output->root) = *tree->metaObject(); - if (!tree->metadata.isEmpty()) + if (!tree->metadata.isEmpty()) QmlEnginePrivate::get(engine)->registerCompositeType(output); } @@ -807,7 +807,9 @@ void QmlCompiler::genObject(QmlParser::Object *obj) meta.line = -1; meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); - meta.storeMeta.slotData = -1; + meta.storeMeta.propertyCache = output->propertyCaches.count(); + // ### Surely the creation of this property cache could be more efficient + output->propertyCaches << QmlPropertyCache::create(engine, obj->metaObject()); output->bytecode << meta; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 447c421..677aba7 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -62,6 +62,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -99,6 +100,7 @@ public: int index; int type; }; + QAbstractDynamicMetaObject root; QList primitives; QList floatData; @@ -108,6 +110,7 @@ public: QList locations; QList bytecode; QList programs; + QList propertyCaches; void dumpInstructions(); private: diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index ade961f..b4c87b8 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE class QmlCompiledData; class QmlAbstractBinding; class QmlContext; +class QmlPropertyCache; class QmlDeclarativeData : public QDeclarativeData { public: @@ -85,6 +86,8 @@ public: QHash *attachedProperties; + QmlPropertyCache *propertyCache; + static QmlDeclarativeData *get(const QObject *object, bool create = false) { QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 72603ed..757670b 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -41,11 +41,12 @@ #undef QT3_SUPPORT // don't want it here - it just causes bugs (which is why we removed it) -#include +#include #include #include #include #include +#include #ifdef QT_SCRIPTTOOLS_LIB #include @@ -192,6 +193,8 @@ QmlEnginePrivate::~QmlEnginePrivate() contextClass = 0; delete objectClass; objectClass = 0; + delete objectClass2; + objectClass2 = 0; delete valueTypeClass; valueTypeClass = 0; delete typeNameClass; @@ -211,6 +214,9 @@ QmlEnginePrivate::~QmlEnginePrivate() clear(parserStatus[ii]); for(QHash::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter) (*iter)->release(); + for(QHash::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter) + (*iter)->release(); + } void QmlEnginePrivate::clear(SimpleList &bvs) @@ -236,6 +242,7 @@ void QmlEnginePrivate::init() scriptEngine.installTranslatorFunctions(); contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); + objectClass2 = new QScriptDeclarativeClass(&scriptEngine); valueTypeClass = new QmlValueTypeScriptClass(q); typeNameClass = new QmlTypeNameScriptClass(q); rootContext = new QmlContext(q,true); @@ -700,7 +707,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt) : context(ctxt), bindings(0), bindingBitsSize(0), bindingBits(0), outerContext(0), lineNumber(0), columnNumber(0), deferredComponent(0), - deferredIdx(0), attachedProperties(0) + deferredIdx(0), attachedProperties(0), propertyCache(0) { } @@ -725,6 +732,9 @@ void QmlDeclarativeData::destroyed(QObject *object) if (bindingBits) free(bindingBits); + if (propertyCache) + propertyCache->release(); + delete this; } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 74e24d4..68019e2 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -72,6 +72,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -88,6 +89,7 @@ class QScriptEngineDebugger; class QNetworkReply; class QNetworkAccessManager; class QmlAbstractBinding; +class QScriptDeclarativeClass; class QmlEnginePrivate : public QObjectPrivate { @@ -149,6 +151,7 @@ public: } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; + QScriptDeclarativeClass *objectClass2; QmlValueTypeScriptClass *valueTypeClass; QmlTypeNameScriptClass *typeNameClass; // Used by DOM Core 3 API @@ -212,10 +215,17 @@ public: // ### Fixme typedef QHash, bool> FunctionCache; FunctionCache functionCache; - QHash propertyCache; - static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) { - if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0; - return &priv->propertyCache[obj->metaObject()]; + QHash propertyCache; + QmlPropertyCache *cache(QObject *obj) { + Q_Q(QmlEngine); + if (!obj || QObjectPrivate::get(obj)->metaObject) return 0; + const QMetaObject *mo = obj->metaObject(); + QmlPropertyCache *rv = propertyCache.value(mo); + if (!rv) { + rv = QmlPropertyCache::create(q, mo); + propertyCache.insert(mo, rv); + } + return rv; } struct Imports { diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index b71c6e3..18439f4 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -69,7 +69,7 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count; break; case QmlInstruction::StoreMetaObject: - qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData; + qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t"; break; case QmlInstruction::StoreFloat: qWarning() << idx << "\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 2c9ceac..e62bfdf 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -175,8 +175,8 @@ public: } create; struct { int data; - int slotData; int aliasData; + int propertyCache; } storeMeta; struct { int value; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index efc4a2b..f7882dc 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -58,56 +58,6 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE -QmlMetaObjectCache::QmlMetaObjectCache() -: propertyCache(0) -{ -} - -void QmlMetaObjectCache::init(const QMetaObject *metaObject) -{ - if (propertyCache || !metaObject) - return; - - int propCount = metaObject->propertyCount(); - - propertyCache = new Data[propCount]; - for (int ii = 0; ii < propCount; ++ii) { - QMetaProperty p = metaObject->property(ii); - propertyCache[ii].propType = p.userType(); - propertyCache[ii].coreIndex = ii; - propertyCache[ii].name = QLatin1String(p.name()); - - propertyNameCache.insert(propertyCache[ii].name, ii); - } -} - -QmlMetaObjectCache::~QmlMetaObjectCache() -{ - delete [] propertyCache; -} - -QmlMetaObjectCache::Data * -QmlMetaObjectCache::property(int index, const QMetaObject *metaObject) -{ - init(metaObject); - - return propertyCache + index; -} - -QmlMetaObjectCache::Data * -QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) -{ - init(metaObject); - - QHash::ConstIterator iter = propertyNameCache.find(name); - - if (iter != propertyNameCache.end()) { - return propertyCache + *iter; - } else { - return 0; - } -} - /*! \class QmlMetaProperty \brief The QmlMetaProperty class abstracts accessing QML properties. @@ -258,11 +208,17 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) } // Property - QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + QmlPropertyCache *cache = 0; + QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); + if (ddata) + cache = ddata->propertyCache; + if (!cache) + cache = enginePrivate?enginePrivate->cache(obj):0; + if (cache) { - QmlMetaObjectCache::Data *data = - cache->property(name, obj->metaObject()); - if (data) { + QmlPropertyCache::Data *data = cache->property(name); + + if (data && !data->isFunction) { type = QmlMetaProperty::Property; propType = data->propType; coreIdx = data->coreIndex; @@ -272,7 +228,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData()); propType = p.userType(); coreIdx = p.propertyIndex(); - if (p.name()) + if (p.name()) type = QmlMetaProperty::Property; } } @@ -1186,13 +1142,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) } else if (d->type & Property) { - QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0; d->coreIdx = id; if (cache) { - QmlMetaObjectCache::Data *data = - cache->property(id, obj->metaObject()); + QmlPropertyCache::Data *data = cache->property(id); d->propType = data->propType; d->name = data->name; } else { diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 1ccf913..0d96174 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -58,28 +58,6 @@ QT_BEGIN_NAMESPACE -class QmlMetaObjectCache -{ -public: - QmlMetaObjectCache(); - ~QmlMetaObjectCache(); - - struct Data { - int propType; - int coreIndex; - QString name; - }; - - Data *property(const QString &, const QMetaObject *); - Data *property(int, const QMetaObject *); - -private: - void init(const QMetaObject *); - - Data *propertyCache; - QHash propertyNameCache; -}; - class QmlContext; class QmlMetaPropertyPrivate { diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp new file mode 100644 index 0000000..f88b3a3 --- /dev/null +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -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$ +** +****************************************************************************/ + +#include "qmlpropertycache_p.h" +#include "qmlengine_p.h" + +QmlPropertyCache::QmlPropertyCache() +{ +} + +QmlPropertyCache::~QmlPropertyCache() +{ + for (int ii = 0; ii < indexCache.count(); ++ii) + indexCache.at(ii)->release(); + + for (StringCache::ConstIterator iter = stringCache.begin(); + iter != stringCache.end(); ++iter) + (*iter)->release(); + + for (IdentifierCache::ConstIterator iter = identifierCache.begin(); + iter != identifierCache.end(); ++iter) + (*iter)->release(); +} + +// ### Optimize - check engine for the parent meta object etc. +QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject) +{ + Q_ASSERT(engine); + Q_ASSERT(metaObject); + + QmlPropertyCache *cache = new QmlPropertyCache; + + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + // ### The properties/methods should probably be spliced on a per-metaobject basis + int propCount = metaObject->propertyCount(); + + cache->indexCache.resize(propCount); + for (int ii = propCount - 1; ii >= 0; --ii) { + QMetaProperty p = metaObject->property(ii); + QString propName = QLatin1String(p.name()); + + QScriptDeclarativeClass::PersistentIdentifier *data = + enginePriv->objectClass2->createPersistentIdentifier(propName); + data->propType = p.userType(); + data->coreIndex = ii; + data->name = propName; + + cache->indexCache[ii] = data; + + if (cache->stringCache.contains(propName)) + continue; + + cache->stringCache.insert(propName, data); + cache->identifierCache.insert(data->identifier, data); + data->addref(); + data->addref(); + } + + int methodCount = metaObject->methodCount(); + for (int ii = methodCount - 1; ii >= 0; --ii) { + QMetaMethod m = metaObject->method(ii); + QString methodName = QLatin1String(m.signature()); + + int parenIdx = methodName.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + methodName = methodName.left(parenIdx); + + if (cache->stringCache.contains(methodName)) + continue; + + QScriptDeclarativeClass::PersistentIdentifier *data = + enginePriv->objectClass2->createPersistentIdentifier(methodName); + cache->stringCache.insert(methodName, data); + cache->identifierCache.insert(data->identifier, data); + data->addref(); + data->addref(); + + data->isFunction = true; + } + + return cache; +} + +QmlPropertyCache::Data * +QmlPropertyCache::property(int index) const +{ + if (index < 0 || index >= indexCache.count()) + return 0; + + return indexCache.at(index); +} + +QmlPropertyCache::Data * +QmlPropertyCache::property(const QString &str) const +{ + return stringCache.value(str); +} + diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h new file mode 100644 index 0000000..c10fafa --- /dev/null +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROPERTYCACHE_P_H +#define QMLPROPERTYCACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QMetaProperty; +class QmlPropertyCache : public QmlRefCount +{ +public: + QmlPropertyCache(); + virtual ~QmlPropertyCache(); + + struct Data : public QmlRefCount { + Data() : isFunction(false) {} + + bool isFunction; + int propType; + int coreIndex; + QString name; + }; + + static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); + + Data *property(const QScriptDeclarativeClass::Identifier &id) const { + return identifierCache.value(id); + } + + Data *property(const QString &) const; + Data *property(int) const; + +private: + typedef QVector *> IndexCache; + typedef QHash *> StringCache; + typedef QHash *> IdentifierCache; + + IndexCache indexCache; + StringCache stringCache; + IdentifierCache identifierCache; +}; + +QT_END_NAMESPACE + +#endif // QMLPROPERTYCACHE_P_H diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 44b17e6..a5d2732 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -143,6 +143,7 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, const QList &customTypeData = comp->customTypeData; const QList &intData = comp->intData; const QList &floatData = comp->floatData; + const QList &propertyCaches = comp->propertyCaches; QmlEnginePrivate::SimpleList bindValues; @@ -259,9 +260,15 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, const QByteArray &metadata = datas.at(instr.storeMeta.data); QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); - const QmlVMEMetaData *data = (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(); + const QmlVMEMetaData *data = + (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(); (void)new QmlVMEMetaObject(target, &mo, data, comp); + + QmlDeclarativeData *ddata = QmlDeclarativeData::get(target, true); + if (ddata->propertyCache) ddata->propertyCache->release(); + ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); + ddata->propertyCache->addref(); } break; -- cgit v0.12 From dff7f0593d86e90eb14c805a96ebbda778f45a82 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 30 Sep 2009 18:13:04 +1000 Subject: Improve script lookup caching --- demos/declarative/samegame/content/samegame.js | 3 + src/declarative/qml/qml.pri | 10 +- src/declarative/qml/qmlcompiler.cpp | 20 +- src/declarative/qml/qmlcompiler_p.h | 4 +- src/declarative/qml/qmlcontext.cpp | 47 ++-- src/declarative/qml/qmlcontext_p.h | 10 +- src/declarative/qml/qmlcontextscriptclass.cpp | 190 +++++++++++++++++ src/declarative/qml/qmlcontextscriptclass_p.h | 89 ++++++++ src/declarative/qml/qmlengine.cpp | 264 +---------------------- src/declarative/qml/qmlengine_p.h | 62 +----- src/declarative/qml/qmlinstruction_p.h | 2 +- src/declarative/qml/qmlintegercache.cpp | 108 ++++++++++ src/declarative/qml/qmlintegercache_p.h | 103 +++++++++ src/declarative/qml/qmlmetaproperty.cpp | 2 +- src/declarative/qml/qmlobjectscriptclass.cpp | 283 +++++++++++++++++++++++++ src/declarative/qml/qmlobjectscriptclass_p.h | 98 +++++++++ src/declarative/qml/qmlpropertycache.cpp | 20 +- src/declarative/qml/qmlpropertycache_p.h | 37 +++- src/declarative/qml/qmlvme.cpp | 4 +- src/script/api/qscriptvalue.cpp | 5 + src/script/bridge/qscriptdeclarativeclass.cpp | 13 ++ src/script/bridge/qscriptdeclarativeclass_p.h | 2 + 22 files changed, 1021 insertions(+), 355 deletions(-) create mode 100644 src/declarative/qml/qmlcontextscriptclass.cpp create mode 100644 src/declarative/qml/qmlcontextscriptclass_p.h create mode 100644 src/declarative/qml/qmlintegercache.cpp create mode 100644 src/declarative/qml/qmlintegercache_p.h create mode 100644 src/declarative/qml/qmlobjectscriptclass.cpp create mode 100644 src/declarative/qml/qmlobjectscriptclass_p.h diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js index e42b7cc..4a9179b 100755 --- a/demos/declarative/samegame/content/samegame.js +++ b/demos/declarative/samegame/content/samegame.js @@ -38,6 +38,7 @@ function initBoard() scoreName.forceClose(); dialog.forceClose(); + var a = new Date(); //Initialize Board board = new Array(maxIndex); gameCanvas.score = 0; @@ -48,6 +49,8 @@ function initBoard() } } timer = new Date(); + + print(timer.valueOf() - a.valueOf()); } var fillFound;//Set after a floodFill call to the number of tiles found diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 216adb1..1a6dad3 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -35,7 +35,10 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlsqldatabase.cpp \ qml/qmetaobjectbuilder.cpp \ qml/qmlwatcher.cpp \ - qml/qmlpropertycache.cpp + qml/qmlpropertycache.cpp \ + qml/qmlintegercache.cpp \ + qml/qmlobjectscriptclass.cpp \ + qml/qmlcontextscriptclass.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -88,7 +91,10 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlsqldatabase_p.h \ qml/qmetaobjectbuilder_p.h \ qml/qmlwatcher_p.h \ - qml/qmlpropertycache_p.h + qml/qmlpropertycache_p.h \ + qml/qmlintegercache_p.h \ + qml/qmlobjectscriptclass_p.h \ + qml/qmlcontextscriptclass_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 0b4ac20..5cb2158 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -633,7 +633,7 @@ void QmlCompiler::compileTree(Object *tree) init.line = 0; init.init.bindingsSize = compileState.bindings.count(); init.init.parserStatusSize = compileState.parserStatusCount; - init.init.idSize = compileState.ids.count(); + init.init.contextCache = genContextCache(); output->bytecode << init; genObject(tree); @@ -964,7 +964,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj) init.type = QmlInstruction::Init; init.init.bindingsSize = compileState.bindings.count(); init.init.parserStatusSize = compileState.parserStatusCount; - init.init.idSize = compileState.ids.count(); + init.init.contextCache = genContextCache(); init.line = obj->location.start.line; output->bytecode << init; @@ -2263,6 +2263,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, output->bytecode << store; } +int QmlCompiler::genContextCache() +{ + if (compileState.ids.count() == 0) + return -1; + + QmlIntegerCache *cache = new QmlIntegerCache(engine); + + for (QHash::ConstIterator iter = compileState.ids.begin(); + iter != compileState.ids.end(); + ++iter) + cache->add(iter.key(), (*iter)->idIndex); + + output->contextCaches.append(cache); + return output->contextCaches.count() - 1; +} + bool QmlCompiler::completeComponentBuild() { for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) { diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 677aba7..1cb66c7 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -63,6 +63,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -111,6 +112,7 @@ public: QList bytecode; QList programs; QList propertyCaches; + QList contextCaches; void dumpInstructions(); private: @@ -232,7 +234,7 @@ private: QmlParser::Property *prop, QmlParser::Object *obj, QmlParser::Property *valueTypeProperty = 0); - + int genContextCache(); int componentTypeRef(); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 97ab375..1c9d177 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() -: parent(0), engine(0), isInternal(false), notifyIndex(-1), +: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1), highPriorityCount(0), expressions(0), idValues(0), idValueCount(0) { } @@ -103,8 +103,8 @@ void QmlContextPrivate::init() //set scope chain QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - QScriptValue scopeObj = - scriptEngine->newObject(QmlEnginePrivate::get(engine)->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q))); + QScriptValue scopeObj = QmlEnginePrivate::get(engine)->contextClass->newContext(q); + //### no longer need to push global object once we switch to JSC (test with objects added to globalObject) //if (parent) // scopeChain = parent->d_func()->scopeChain; @@ -304,6 +304,9 @@ QmlContext::~QmlContext() d->contextObjects.clear(); delete [] d->idValues; + + if (d->propertyNames) + d->propertyNames->release(); } void QmlContextPrivate::invalidateEngines() @@ -361,13 +364,16 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value) QObject *o = QmlMetaType::toQObject(value); setContextProperty(name, o); } else { - QHash::ConstIterator iter = d->propertyNames.find(name); - if(iter == d->propertyNames.end()) { - d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count()); + + if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine); + + int idx = d->propertyNames->value(name); + if (idx == -1) { + d->propertyNames->add(name, d->idValueCount + d->propertyValues.count()); d->propertyValues.append(value); } else { - d->propertyValues[*iter] = value; - QMetaObject::activate(this, *iter + d->notifyIndex, 0); + d->propertyValues[idx] = value; + QMetaObject::activate(this, idx + d->notifyIndex, 0); } } } @@ -380,15 +386,19 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx, notifyIndex = q->metaObject()->methodCount(); } - propertyNames.insert(name, idx); + propertyNames->add(name, idx); idValues[idx].priv = this; idValues[idx] = obj; } -void QmlContextPrivate::setIdPropertyCount(int count) +void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data) { - idValues = new ContextGuard[count]; - idValueCount = count; + Q_ASSERT(!propertyNames); + propertyNames = data; + propertyNames->addref(); + + idValueCount = data->count(); + idValues = new ContextGuard[idValueCount]; } /*! @@ -402,14 +412,15 @@ void QmlContext::setContextProperty(const QString &name, QObject *value) if (d->notifyIndex == -1) d->notifyIndex = this->metaObject()->methodCount(); - QHash::ConstIterator iter = d->propertyNames.find(name); - if(iter == d->propertyNames.end()) { - d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count()); + if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine); + int idx = d->propertyNames->value(name); + + if (idx == -1) { + d->propertyNames->add(name, d->idValueCount + d->propertyValues.count()); d->propertyValues.append(QVariant::fromValue(value)); } else { - int idx = *iter; - d->propertyValues[*iter] = QVariant::fromValue(value); - QMetaObject::activate(this, *iter + d->notifyIndex, 0); + d->propertyValues[idx] = QVariant::fromValue(value); + QMetaObject::activate(this, idx + d->notifyIndex, 0); } } diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index b305408..64faa6d 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -61,6 +61,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -82,7 +83,8 @@ public: QmlEngine *engine; bool isInternal; - QHash propertyNames; + QmlIntegerCache *propertyNames; +// QHash propertyNames; QList propertyValues; int notifyIndex; @@ -125,9 +127,13 @@ public: ContextGuard *idValues; int idValueCount; void setIdProperty(const QString &, int, QObject *); - void setIdPropertyCount(int); + void setIdPropertyData(QmlIntegerCache *); void destroyed(ContextGuard *); + static QmlContextPrivate *get(QmlContext *context) { + return static_cast(QObjectPrivate::get(context)); + } + // Only used for debugging QList > instances; }; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp new file mode 100644 index 0000000..baea60a --- /dev/null +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlcontextscriptclass_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +struct ContextData { + ContextData(QmlContext *c) : context(c) {} + QGuard context; +}; + +/* + The QmlContextScriptClass handles property access for a QmlContext + via QtScript. + */ +QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), + lastPropertyIndex(-1), lastDefaultObject(-1) +{ +} + +QmlContextScriptClass::~QmlContextScriptClass() +{ +} + +QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return newObject(scriptEngine, this, (Object)new ContextData(context)); +} + +QScriptClass::QueryFlags +QmlContextScriptClass::queryProperty(const Object &object, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(flags); + QmlContext *bindContext = ((ContextData *)object)->context.data(); + if (!bindContext) + return 0; + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + + lastPropertyIndex = -1; + lastDefaultObject = -1; + + lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1; + if (lastPropertyIndex != -1) + return QScriptClass::HandlesReadAccess; + + // ### Check for attached properties +#if 0 + QmlType *type = 0; ImportedNamespace *ns = 0; + if (currentExpression && bindContext == currentExpression->context() && + propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) { + + if (type || ns) { + // Must be either an attached property, or an enum + resolveData.object = bindContext->d_func()->defaultObjects.first(); + resolveData.type = type; + resolveData.ns = ns; + return QScriptClass::HandlesReadAccess; + } + + } +#endif + + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags); + + if (rv) { + lastDefaultObject = ii; + return rv; + } + } + + return 0; +} + +QScriptValue QmlContextScriptClass::property(const Object &object, const Identifier &name) +{ + Q_UNUSED(object); + + Q_ASSERT(lastPropertyIndex != -1 || lastDefaultObject != -1); + + QmlContext *bindContext = ((ContextData *)object)->context.data(); + Q_ASSERT(bindContext); + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + + + // ### Check for attached properties +#if 0 + if (resolveData.type || resolveData.ns) { + QmlTypeNameBridge tnb = { + resolveData.object, + resolveData.type, + resolveData.ns + }; + return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb))); + } +#endif + + if (lastPropertyIndex != -1) { + + QScriptValue rv; + if (lastPropertyIndex < cp->idValueCount) { + rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data()); + } else { + QVariant value = cp->propertyValues.at(lastPropertyIndex); + if (QmlMetaType::isObject(value.userType())) { + rv = ep->objectClass->newQObject(QmlMetaType::toQObject(value)); + } else { + // ### Shouldn't this be qScriptValueFromValue() + rv = ep->scriptEngine.newVariant(value); + } + } + + ep->capturedProperties << + QmlEnginePrivate::CapturedProperty(bindContext, -1, + lastPropertyIndex + cp->notifyIndex); + + return rv; + } else { + + // Default object property + return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name); + + } +} + +void QmlContextScriptClass::setProperty(const Object &object, const Identifier &name, + const QScriptValue &value) +{ + Q_ASSERT(lastDefaultObject != -1); + + QmlContext *bindContext = ((ContextData *)object)->context.data(); + Q_ASSERT(bindContext); + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h new file mode 100644 index 0000000..9ef090d --- /dev/null +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLCONTEXTSCRIPTCLASS_P_H +#define QMLCONTEXTSCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlContext; +class QmlContextScriptClass : public QScriptDeclarativeClass +{ +public: + QmlContextScriptClass(QmlEngine *); + ~QmlContextScriptClass(); + + QScriptValue newContext(QmlContext *); + +protected: + virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + QScriptClass::QueryFlags flags); + virtual QScriptValue property(const Object &, const Identifier &); + virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + +private: + QmlEngine *engine; + + int lastPropertyIndex; + int lastDefaultObject; + + uint m_id; +}; + +QT_END_NAMESPACE + +#endif // QMLCONTEXTSCRIPTCLASS_P_H + diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 757670b..d680fa1 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -193,8 +193,6 @@ QmlEnginePrivate::~QmlEnginePrivate() contextClass = 0; delete objectClass; objectClass = 0; - delete objectClass2; - objectClass2 = 0; delete valueTypeClass; valueTypeClass = 0; delete typeNameClass; @@ -242,7 +240,6 @@ void QmlEnginePrivate::init() scriptEngine.installTranslatorFunctions(); contextClass = new QmlContextScriptClass(q); objectClass = new QmlObjectScriptClass(q); - objectClass2 = new QScriptDeclarativeClass(&scriptEngine); valueTypeClass = new QmlValueTypeScriptClass(q); typeNameClass = new QmlTypeNameScriptClass(q); rootContext = new QmlContext(q,true); @@ -288,95 +285,6 @@ struct QmlValueTypeReference { }; Q_DECLARE_METATYPE(QmlValueTypeReference); -//////////////////////////////////////////////////////////////////// -QScriptClass::QueryFlags -QmlEnginePrivate::queryContext(const QString &propName, uint *id, - QmlContext *bindContext) -{ - resolveData.safetyCheckId++; - *id = resolveData.safetyCheckId; - resolveData.clear(); - - QHash::Iterator contextProperty = - bindContext->d_func()->propertyNames.find(propName); - - if (contextProperty != bindContext->d_func()->propertyNames.end()) { - - resolveData.context = bindContext; - resolveData.contextIndex = *contextProperty; - - return QScriptClass::HandlesReadAccess; - } - - QmlType *type = 0; ImportedNamespace *ns = 0; - if (currentExpression && bindContext == currentExpression->context() && - propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) { - - if (type || ns) { - // Must be either an attached property, or an enum - resolveData.object = bindContext->d_func()->defaultObjects.first(); - resolveData.type = type; - resolveData.ns = ns; - return QScriptClass::HandlesReadAccess; - } - - } - - QScriptClass::QueryFlags rv = 0; - for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { - rv = queryObject(propName, id, - bindContext->d_func()->defaultObjects.at(ii)); - } - - return rv; -} - -QScriptValue QmlEnginePrivate::propertyContext(const QScriptString &name, uint id) -{ - Q_ASSERT(id == resolveData.safetyCheckId); - - if (resolveData.type || resolveData.ns) { - QmlTypeNameBridge tnb = { - resolveData.object, - resolveData.type, - resolveData.ns - }; - return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb))); - } else if (resolveData.context) { - QmlContext *bindContext = resolveData.context; - QmlContextPrivate *contextPrivate = bindContext->d_func(); - int index = resolveData.contextIndex; - - QScriptValue rv; - if (index < contextPrivate->idValueCount) { - rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data()))); - } else { - QVariant value = contextPrivate->propertyValues.at(index); - if (QmlMetaType::isObject(value.userType())) { - rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value)); - } else { - rv = scriptEngine.newVariant(value); - } - } - capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex); - return rv; - - } else { - - return propertyObject(name, resolveData.object, id); - - } - - return QScriptValue(); -} - -void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id) -{ - // As context properties cannot be written, we can assume that the - // write is a object property write - setPropertyObject(value, id); -} - void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id) { Q_ASSERT(id == resolveData.safetyCheckId); @@ -430,7 +338,7 @@ QmlEnginePrivate::queryObject(const QString &propName, return rv; } -QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, +QScriptValue QmlEnginePrivate::propertyObject(const QString &propName, QObject *obj, uint id) { Q_ASSERT(id == resolveData.safetyCheckId); @@ -461,7 +369,7 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, if (!varobj) varobj = qvariant_cast(var); if (varobj) { - return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj))); + return objectClass->newQObject(varobj); } else { return qScriptValueFromValue(&scriptEngine, var); } @@ -784,8 +692,8 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit) QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object, QmlEngine* engine) { - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newQObject(object, QScriptEngine::AutoOwnership)); + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + return enginePriv->objectClass->newQObject(object); } /*! @@ -901,7 +809,7 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi QUrl url; if(ctxt->argumentCount() > 2) url = QUrl(ctxt->argument(2).toString()); - QObject *parentArg = ctxt->argument(1).data().toQObject(); + QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1)); QmlContext *qmlCtxt = qmlContext(parentArg); url = qmlCtxt->resolvedUrl(url); QmlComponent component(activeEngine, qml.toUtf8(), url); @@ -1138,13 +1046,15 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) QmlEnginePrivate *ep = static_cast(QObjectPrivate::get(engine)); + QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); + if (dc == ep->objectClass) + return QVariant::fromValue(ep->objectClass->toQObject(val)); + else if (dc == ep->contextClass) + return QVariant(); + QScriptClass *sc = val.scriptClass(); if (!sc) { return val.toVariant(); - } else if (sc == ep->contextClass) { - return QVariant(); - } else if (sc == ep->objectClass) { - return QVariant::fromValue(val.data().toQObject()); } else if (sc == ep->valueTypeClass) { QmlValueTypeReference ref = qvariant_cast(val.data().toVariant()); @@ -1160,56 +1070,6 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) } ///////////////////////////////////////////////////////////// -/* - The QmlContextScriptClass handles property access for a QmlContext - via QtScript. - */ -QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) - : QmlScriptClass(bindEngine) -{ -} - -QmlContextScriptClass::~QmlContextScriptClass() -{ -} - -QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id) -{ - Q_UNUSED(flags); - QmlContext *bindContext = - static_cast(object.data().toQObject()); - - QString propName = name.toString(); - - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - return ep->queryContext(propName, id, bindContext); -} - -QScriptValue QmlContextScriptClass::property(const QScriptValue &object, - const QScriptString &name, - uint id) -{ - Q_UNUSED(object); - - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - return ep->propertyContext(name, id); -} - -void QmlContextScriptClass::setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value) -{ - Q_UNUSED(object); - Q_UNUSED(name); - - QmlEnginePrivate::get(engine)->setPropertyContext(value, id); -} - -///////////////////////////////////////////////////////////// QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine) : QmlScriptClass(engine), object(0), type(0) { @@ -1365,108 +1225,6 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object, ref.type->write(ref.object, ref.property); } -///////////////////////////////////////////////////////////// -/* - The QmlObjectScriptClass handles property access for QObjects - via QtScript. It is also used to provide a more useful API in - QtScript for QML. - */ - -QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine) -{ - QObject* obj = context->thisObject().data().toQObject(); - QString ret = QLatin1String("Qml Object, "); - if(obj){ - //###Should this be designer or developer details? Dev for now. - //TODO: Can we print the id too? - ret += QLatin1String("\""); - ret += obj->objectName(); - ret += QLatin1String("\" "); - ret += QLatin1String(obj->metaObject()->className()); - ret += QLatin1String("(0x"); - ret += QString::number((quintptr)obj,16); - ret += QLatin1String(")"); - }else{ - ret += QLatin1String("null"); - } - return engine->newVariant(ret); -} - -QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine) -{ - QObject* obj = context->thisObject().data().toQObject(); - if(obj){ - int delay = 0; - if(context->argumentCount() > 0) - delay = context->argument(0).toInt32(); - QTimer::singleShot(delay, obj, SLOT(deleteLater())); - //### Should this be delayed as well? - context->thisObject().setData(QScriptValue(engine, 0)); - } - return engine->nullValue(); -} - -QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) - : QmlScriptClass(bindEngine) -{ - engine = bindEngine; - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); - prototypeObject = scriptEngine->newObject(); - prototypeObject.setProperty(QLatin1String("toStr"),//TODO: Why won't toString work? - scriptEngine->newFunction(QmlObjectToString)); - prototypeObject.setProperty(QLatin1String("destroy"), - scriptEngine->newFunction(QmlObjectDestroy)); -} - -QmlObjectScriptClass::~QmlObjectScriptClass() -{ -} - -QScriptValue QmlObjectScriptClass::prototype() const -{ - return prototypeObject; -} - -QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id) -{ - Q_UNUSED(flags); - QObject *obj = object.data().toQObject(); - QueryFlags rv = 0; - QString propName = name.toString(); - - if (obj) - rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, obj); - - return rv; -} - -QScriptValue QmlObjectScriptClass::property(const QScriptValue &object, - const QScriptString &name, - uint id) -{ - QObject *obj = object.data().toQObject(); - - QScriptValue rv = - QmlEnginePrivate::get(engine)->propertyObject(name, obj, id); - if (rv.isValid()) - return rv; - - return QScriptValue(); -} - -void QmlObjectScriptClass::setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value) -{ - Q_UNUSED(name); - Q_UNUSED(object); - QmlEnginePrivate::get(engine)->setPropertyObject(value, id); -} - - struct QmlEnginePrivate::ImportedNamespace { QStringList urls; QList majversions; diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 68019e2..764cc6c 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -73,6 +73,8 @@ #include #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -100,13 +102,9 @@ public: void init(); - QScriptClass::QueryFlags queryContext(const QString &name, uint *id, - QmlContext *); - QScriptValue propertyContext(const QScriptString &propName, uint id); - void setPropertyContext(const QScriptValue &, uint id); QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *); - QScriptValue propertyObject(const QScriptString &propName, QObject *, + QScriptValue propertyObject(const QString &propName, QObject *, uint id = 0); void setPropertyObject(const QScriptValue &, uint id); @@ -151,7 +149,6 @@ public: } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; - QScriptDeclarativeClass *objectClass2; QmlValueTypeScriptClass *valueTypeClass; QmlTypeNameScriptClass *typeNameClass; // Used by DOM Core 3 API @@ -215,6 +212,7 @@ public: // ### Fixme typedef QHash, bool> FunctionCache; FunctionCache functionCache; + QHash propertyCache; QmlPropertyCache *cache(QObject *obj) { Q_Q(QmlEngine); @@ -285,19 +283,6 @@ public: class QmlScriptClass : public QScriptClass { public: - enum ClassId - { - InvalidId = -1, - - FunctionId = 0x80000000, - VariantPropertyId = 0x40000000, - PropertyId = 0x00000000, - - ClassIdMask = 0xC0000000, - - ClassIdSelectorMask = 0x3F000000, - }; - QmlScriptClass(QmlEngine *); static QVariant toVariant(QmlEngine *, const QScriptValue &); @@ -305,45 +290,6 @@ protected: QmlEngine *engine; }; -class QmlContextScriptClass : public QmlScriptClass -{ -public: - QmlContextScriptClass(QmlEngine *); - ~QmlContextScriptClass(); - - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - virtual void setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value); -}; - -class QmlObjectScriptClass : public QmlScriptClass -{ -public: - QmlObjectScriptClass(QmlEngine *); - ~QmlObjectScriptClass(); - - virtual QScriptValue prototype () const; - QScriptValue prototypeObject; - - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - virtual void setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value); -}; - class QmlTypeNameScriptClass : public QmlScriptClass { public: diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index e62bfdf..38b3191 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -165,7 +165,7 @@ public: struct { int bindingsSize; int parserStatusSize; - int idSize; + int contextCache; } init; struct { int type; diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp new file mode 100644 index 0000000..1bc4086 --- /dev/null +++ b/src/declarative/qml/qmlintegercache.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlintegercache_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +QmlIntegerCache::QmlIntegerCache(QmlEngine *e) +: engine(e) +{ +} + +QmlIntegerCache::~QmlIntegerCache() +{ + qDeleteAll(stringCache); +} + +void QmlIntegerCache::add(const QString &id, int value) +{ + Q_ASSERT(!stringCache.contains(id)); + + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + // ### use contextClass + QScriptDeclarativeClass::PersistentIdentifier *d = + enginePriv->objectClass->createPersistentIdentifier(id); + d->value = value; + + stringCache.insert(id, d); + identifierCache.insert(d->identifier, d); +} + +int QmlIntegerCache::value(const QString &id) +{ + Data *d = stringCache.value(id); + return d?d->value:-1; +} + +QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engine) +{ + Q_ASSERT(type); + Q_ASSERT(engine); + + QmlIntegerCache *cache = new QmlIntegerCache(engine); + + const QMetaObject *mo = type->metaObject(); + + for (int ii = mo->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum enumerator = mo->enumerator(ii); + + for (int jj = 0; jj < enumerator.keyCount(); ++jj) { + QString name = QLatin1String(enumerator.key(jj)); + int value = enumerator.value(jj); + + if (!name.at(0).isUpper()) + continue; + + if (cache->stringCache.contains(name)) + continue; + + cache->add(name, value); + } + } + + return cache; +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h new file mode 100644 index 0000000..fda80c6 --- /dev/null +++ b/src/declarative/qml/qmlintegercache_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLINTEGERCACHE_P_H +#define QMLINTEGERCACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlType; +class QmlEngine; +class QmlIntegerCache : public QmlRefCount +{ +public: + QmlIntegerCache(QmlEngine *); + virtual ~QmlIntegerCache(); + + inline int count() const; + void add(const QString &, int); + int value(const QString &); + inline int value(const QScriptDeclarativeClass::Identifier &id) const; + + static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *); +private: + struct Data { + int value; + }; + + typedef QHash *> StringCache; + typedef QHash *> IdentifierCache; + + StringCache stringCache; + IdentifierCache identifierCache; + QmlEngine *engine; +}; + +int QmlIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const +{ + Data *d = identifierCache.value(id); + return d?d->value:-1; +} + +int QmlIntegerCache::count() const +{ + return stringCache.count(); +} + +QT_END_NAMESPACE + +#endif // QMLINTEGERCACHE_P_H + diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index f7882dc..ec143a7 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -218,7 +218,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (cache) { QmlPropertyCache::Data *data = cache->property(name); - if (data && !data->isFunction) { + if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) { type = QmlMetaProperty::Property; propType = data->propType; coreIdx = data->coreIndex; diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp new file mode 100644 index 0000000..0ae1809 --- /dev/null +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlobjectscriptclass_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +struct ObjectData { + ObjectData(QObject *o) : object(o) {} + QGuard object; +}; + +static QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine) +{ + QObject* obj = context->thisObject().data().toQObject(); + QString ret = QLatin1String("Qml Object, "); + if(obj){ + //###Should this be designer or developer details? Dev for now. + //TODO: Can we print the id too? + ret += QLatin1String("\""); + ret += obj->objectName(); + ret += QLatin1String("\" "); + ret += QLatin1String(obj->metaObject()->className()); + ret += QLatin1String("(0x"); + ret += QString::number((quintptr)obj,16); + ret += QLatin1String(")"); + }else{ + ret += QLatin1String("null"); + } + return engine->newVariant(ret); +} + +static QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine) +{ + QObject* obj = context->thisObject().toQObject(); + if(obj){ + int delay = 0; + if(context->argumentCount() > 0) + delay = context->argument(0).toInt32(); + obj->deleteLater(); + //### Should this be delayed as well? + context->thisObject().setData(QScriptValue(engine, 0)); + } + return engine->nullValue(); +} + +/* + The QmlObjectScriptClass handles property access for QObjects + via QtScript. It is also used to provide a more useful API in + QtScript for QML. + */ +QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0), + engine(bindEngine) +{ + engine = bindEngine; + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); + + m_destroy = scriptEngine->newFunction(QmlObjectDestroy); + m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); +} + +QmlObjectScriptClass::~QmlObjectScriptClass() +{ + delete m_destroyId; +} + +QScriptValue QmlObjectScriptClass::newQObject(QObject *object) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return newObject(scriptEngine, this, (Object)new ObjectData(object)); +} + +QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const +{ + return value.toQObject(); +} + +QScriptClass::QueryFlags +QmlObjectScriptClass::queryProperty(const Object &object, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + return queryProperty(toQObject(object), name, flags); +} + +QScriptClass::QueryFlags +QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(flags); + lastData = 0; + + if (name == m_destroyId->identifier) + return QScriptClass::HandlesReadAccess; + + if (!obj) + return 0; + + QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); + QmlPropertyCache *cache = 0; + QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); + if (ddata) + cache = ddata->propertyCache; + if (!cache) { + cache = enginePrivate->cache(obj); + if (ddata) { cache->addref(); ddata->propertyCache = cache; } + } + + if (cache) { + QmlPropertyCache::Data *property = cache->property(name); + if (!property) return 0; + + if (flags == QScriptClass::HandlesReadAccess) { + lastData = property; + return QScriptClass::HandlesReadAccess; + } else if (property->propType > 0 && property->propType < QVariant::UserType) { + lastData = property; + return flags; + } + } + + // Fallback + return QmlEnginePrivate::get(engine)->queryObject(toString(name), &m_id, obj); +} + +QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifier &name) +{ + return property(toQObject(object), name); +} + +QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name) +{ + if (name == m_destroyId->identifier) + return m_destroy; + + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + if (!obj) { + return QScriptValue(); + } else if (lastData) { + + if (lastData->flags & QmlPropertyCache::Data::IsFunction) { + // ### Optimize + QScriptValue sobj = scriptEngine->newQObject(obj); + return sobj.property(toString(name)); + } else { + QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); + if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { + enginePriv->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, + lastData->notifyIndex); + } + + if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { + QObject *rv = *(QObject **)var.constData(); + return newQObject(rv); + } else { + return qScriptValueFromValue(scriptEngine, var); + } + } + + } else { + return QmlEnginePrivate::get(engine)->propertyObject(toString(name), obj, m_id); + } +} + +void QmlObjectScriptClass::setProperty(const Object &object, + const Identifier &name, + const QScriptValue &value) +{ + return setProperty(toQObject(object), name, value); +} + +void QmlObjectScriptClass::setProperty(QObject *obj, + const Identifier &name, + const QScriptValue &value) +{ + Q_UNUSED(name); + Q_UNUSED(object); + + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + if (!obj) { + return; + } else if (lastData) { + switch (lastData->propType) { + case 1: + { + bool b = value.toBoolean(); + void *a[1]; + a[0] = &b; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); + } + break; + + case 2: + { + int b = value.toInteger(); + void *a[1]; + a[0] = &b; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); + } + break; + + case 6: + { + double b = value.toNumber(); + void *a[1]; + a[0] = &b; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); + } + break; + + default: + { + QMetaProperty p = obj->metaObject()->property(lastData->coreIndex); + p.write(obj, value.toVariant()); + } + } + } else { + QmlEnginePrivate::get(engine)->setPropertyObject(value, m_id); + } +} + +QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok) +{ + if (ok) *ok = true; + + ObjectData *data = (ObjectData*)object; + return data->object.data(); +} + +void QmlObjectScriptClass::destroyed(const Object &object) +{ + ObjectData *data = (ObjectData*)object; + delete data; +} + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h new file mode 100644 index 0000000..c25718c --- /dev/null +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLOBJECTSCRIPTCLASS_P_H +#define QMLOBJECTSCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlObjectScriptClass : public QScriptDeclarativeClass +{ +public: + QmlObjectScriptClass(QmlEngine *); + ~QmlObjectScriptClass(); + + QScriptValue newQObject(QObject *); + QObject *toQObject(const QScriptValue &) const; + + QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &, + QScriptClass::QueryFlags flags); + QScriptValue property(QObject *, const Identifier &); + void setProperty(QObject *, const Identifier &name, const QScriptValue &); + +protected: + virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + QScriptClass::QueryFlags flags); + + virtual QScriptValue property(const Object &, const Identifier &); + virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + virtual QObject *toQObject(const Object &, bool *ok = 0); + virtual void destroyed(const Object &); + +private: + uint m_id; + QmlPropertyCache::Data *lastData; + struct Dummy {}; + PersistentIdentifier *m_destroyId; + QScriptValue m_destroy; + QmlEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QMLOBJECTSCRIPTCLASS_P_H + diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index f88b3a3..95b819a 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -42,6 +42,8 @@ #include "qmlpropertycache_p.h" #include "qmlengine_p.h" +QT_BEGIN_NAMESPACE + QmlPropertyCache::QmlPropertyCache() { } @@ -78,12 +80,19 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject QMetaProperty p = metaObject->property(ii); QString propName = QLatin1String(p.name()); - QScriptDeclarativeClass::PersistentIdentifier *data = - enginePriv->objectClass2->createPersistentIdentifier(propName); + QScriptDeclarativeClass::PersistentIdentifier *data = + enginePriv->objectClass->createPersistentIdentifier(propName); + data->propType = p.userType(); data->coreIndex = ii; + data->notifyIndex = p.notifySignalIndex(); data->name = propName; + if (p.isConstant()) + data->flags |= Data::IsConstant; + if (QmlMetaType::isObject(data->propType)) + data->flags |= Data::IsQObjectDerived; + cache->indexCache[ii] = data; if (cache->stringCache.contains(propName)) @@ -107,14 +116,14 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject if (cache->stringCache.contains(methodName)) continue; - QScriptDeclarativeClass::PersistentIdentifier *data = - enginePriv->objectClass2->createPersistentIdentifier(methodName); + QScriptDeclarativeClass::PersistentIdentifier *data = + enginePriv->objectClass->createPersistentIdentifier(methodName); cache->stringCache.insert(methodName, data); cache->identifierCache.insert(data->identifier, data); data->addref(); data->addref(); - data->isFunction = true; + data->flags |= Data::IsFunction; } return cache; @@ -135,3 +144,4 @@ QmlPropertyCache::property(const QString &str) const return stringCache.value(str); } +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index c10fafa..21c8ef3 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -67,33 +67,50 @@ public: QmlPropertyCache(); virtual ~QmlPropertyCache(); - struct Data : public QmlRefCount { - Data() : isFunction(false) {} + struct Data { + inline Data(); - bool isFunction; + enum Flag { IsFunction = 0x00000001, + IsQObjectDerived = 0x00000002, + IsConstant = 0x00000004 }; + Q_DECLARE_FLAGS(Flags, Flag) + + Flags flags; int propType; int coreIndex; + int notifyIndex; QString name; }; static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); - Data *property(const QScriptDeclarativeClass::Identifier &id) const { - return identifierCache.value(id); - } - + inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; Data *property(const QString &) const; Data *property(int) const; private: - typedef QVector *> IndexCache; - typedef QHash *> StringCache; - typedef QHash *> IdentifierCache; + struct RData : public Data, public QmlRefCount {}; + + typedef QVector *> IndexCache; + typedef QHash *> StringCache; + typedef QHash *> IdentifierCache; IndexCache indexCache; StringCache stringCache; IdentifierCache identifierCache; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlPropertyCache::Data::Flags); + +QmlPropertyCache::Data::Data() +: flags(0), propType(0), coreIndex(-1), notifyIndex(-1) +{ +} + +QmlPropertyCache::Data * +QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const +{ + return identifierCache.value(id); +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index a5d2732..4ba412b 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -166,8 +166,8 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (instr.init.parserStatusSize) parserStatus = QmlEnginePrivate::SimpleList(instr.init.parserStatusSize); - if (instr.init.idSize) - cp->setIdPropertyCount(instr.init.idSize); + if (instr.init.contextCache != -1) + cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); } break; diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index f2716e4..d8b4822 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -71,6 +71,7 @@ #include "bridge/qscriptclassobject_p.h" #include "bridge/qscriptvariant_p.h" #include "bridge/qscriptqobject_p.h" +#include "bridge/qscriptdeclarativeclass_p.h" /*! \since 4.3 @@ -1529,6 +1530,8 @@ QVariant QScriptValue::toVariant() const #endif else if (isArray()) return QScriptEnginePrivate::variantListFromArray(*this); + else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) + return dc->toVariant(QScriptDeclarativeClass::object(*this)); // try to convert to primitive JSC::ExecState *exec = d->engine->currentFrame; JSC::JSValue savedException; @@ -1619,6 +1622,8 @@ QObject *QScriptValue::toQObject() const if (isQObject()) { QScriptObject *object = static_cast(JSC::asObject(d->jscValue)); return static_cast(object->delegate())->value(); + } else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) { + return dc->toQObject(QScriptDeclarativeClass::object(*this)); } else if (isVariant()) { QVariant var = toVariant(); int type = var.userType(); diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index c753379..c017e13 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -219,3 +220,15 @@ void QScriptDeclarativeClass::destroyed(const Object &object) Q_UNUSED(object); } +QObject *QScriptDeclarativeClass::toQObject(const Object &, bool *ok) +{ + if (ok) *ok = false; + return 0; +} + +QVariant QScriptDeclarativeClass::toVariant(const Object &, bool *ok) +{ + if (ok) *ok = false; + return QVariant(); +} + diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 5705a51..a00a286 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -112,6 +112,8 @@ public: virtual QStringList propertyNames(const Object &); + virtual QObject *toQObject(const Object &, bool *ok = 0); + virtual QVariant toVariant(const Object &, bool *ok = 0); virtual void destroyed(const Object &); static void destroyPersistentIdentifier(void **); -- cgit v0.12 From 99cf375f554fe01cf47fd4e1a291d4bba62b4018 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 30 Sep 2009 18:51:45 +1000 Subject: Minor QmlMetaProperty cleanup --- src/declarative/qml/qmlmetaproperty.cpp | 53 ++++++++++++++++++++------------- src/declarative/qml/qmlmetaproperty_p.h | 2 ++ 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index ec143a7..fbe41dd 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -646,28 +646,11 @@ QVariant QmlMetaProperty::read() const if (sig && sig->index() == d->coreIdx) return sig->expression()->expression(); } + } else if (type() & Property) { - if (type() & Attached) { - return QVariant::fromValue(d->attachedObject()); - } else if(type() & ValueTypeProperty) { - QmlEnginePrivate *ep = d->context?static_cast(QObjectPrivate::get(d->context->engine())):0; - QmlValueType *valueType = 0; - if (ep) - valueType = ep->valueTypes[d->valueTypeId]; - else - valueType = QmlValueTypeFactory::valueType(d->valueTypeId); - Q_ASSERT(valueType); - - valueType->read(object(), d->coreIdx); - QVariant rv = - valueType->metaObject()->property(d->valueTypeIdx).read(valueType); - if (!ep) - delete valueType; - return rv; - } else { - return d->object->metaObject()->property(d->coreIdx).read(object()); - } + return d->readValueProperty(); + } return QVariant(); } @@ -696,6 +679,36 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) } } +QVariant QmlMetaPropertyPrivate::readValueProperty() +{ + if (type & QmlMetaProperty::Attached) { + + return QVariant::fromValue(attachedObject()); + + } else if(type & QmlMetaProperty::ValueTypeProperty) { + + QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0; + QmlValueType *valueType = 0; + if (ep) + valueType = ep->valueTypes[valueTypeId]; + else + valueType = QmlValueTypeFactory::valueType(valueTypeId); + Q_ASSERT(valueType); + + valueType->read(object, coreIdx); + QVariant rv = + valueType->metaObject()->property(valueTypeIdx).read(valueType); + if (!ep) + delete valueType; + return rv; + + } else { + + return object->metaObject()->property(coreIdx).read(object.data()); + + } +} + void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlMetaProperty::WriteSource source) { diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 0d96174..3193aaf 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -98,6 +98,8 @@ public: QmlMetaProperty::PropertyCategory propertyCategory() const; void writeSignalProperty(const QVariant &); + + QVariant readValueProperty(); void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); static quint32 saveValueType(int, int); -- cgit v0.12 From 69c58d7e1c5713d1d6badeffc6c45eeacb1ba2d8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 1 Oct 2009 13:25:49 +1000 Subject: QmlMetaProperty cleanup --- src/declarative/qml/qmlmetaproperty.cpp | 550 ++++++++++++++----------------- src/declarative/qml/qmlmetaproperty_p.h | 40 +-- src/declarative/qml/qmlpropertycache.cpp | 55 +++- src/declarative/qml/qmlpropertycache_p.h | 35 +- 4 files changed, 348 insertions(+), 332 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index fbe41dd..477377e 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -72,9 +72,7 @@ QmlMetaProperty::QmlMetaProperty() d->q = this; } -/*! - The destructor deletes its heap data. - */ +/*! \internal */ QmlMetaProperty::~QmlMetaProperty() { delete d; d = 0; @@ -114,11 +112,9 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj) object = obj; QMetaProperty p = QmlMetaType::defaultProperty(obj); - name = QLatin1String(p.name()); - propType = p.userType();; - coreIdx = p.propertyIndex(); - if (!name.isEmpty()) - type = QmlMetaProperty::Property | QmlMetaProperty::Default; + core.load(p); + if (core.isValid()) + isDefaultProperty = true; } /*! @@ -129,15 +125,12 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj) QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt) : d(new QmlMetaPropertyPrivate) { + Q_ASSERT(obj); + d->q = this; d->context = ctxt; d->object = obj; - d->type = Property; - QMetaProperty p = obj->metaObject()->property(idx); - d->propType = p.userType(); - d->coreIdx = idx; - if (p.name() != 0) - d->name = QLatin1String(p.name()); + d->core.load(obj->metaObject()->property(idx)); } /*! @@ -168,7 +161,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (context && context->engine()) enginePrivate = QmlEnginePrivate::get(context->engine()); - this->name = name; object = obj; if (name.isEmpty() || !obj) @@ -185,8 +177,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0); if (t && t->attachedPropertiesFunction()) { attachedFunc = t->index(); - if (attachedFunc != -1) - type = QmlMetaProperty::Property | QmlMetaProperty::Attached; } typeData->release(); } @@ -200,9 +190,9 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) QString signalName = name.mid(2); signalName[0] = signalName.at(0).toLower(); - findSignalInt(obj, signalName); - if (signal.signature() != 0) { - type = QmlMetaProperty::SignalProperty; + QMetaMethod method = findSignal(obj, signalName); + if (method.signature()) { + core.load(method); return; } } @@ -218,18 +208,13 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (cache) { QmlPropertyCache::Data *data = cache->property(name); - if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) { - type = QmlMetaProperty::Property; - propType = data->propType; - coreIdx = data->coreIndex; - } + if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) + core = *data; + } else { - // Can't cache + // No cache available QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData()); - propType = p.userType(); - coreIdx = p.propertyIndex(); - if (p.name()) - type = QmlMetaProperty::Property; + core.load(p); } } @@ -279,33 +264,31 @@ QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const QmlMetaProperty::PropertyCategory QmlMetaPropertyPrivate::propertyCategory() const { - if (category == QmlMetaProperty::Unknown) { + uint type = q->type(); + + if (type & QmlMetaProperty::ValueTypeProperty) { + return QmlMetaProperty::Normal; + } else if (type & QmlMetaProperty::Attached) { + return QmlMetaProperty::Object; + } else if (type & QmlMetaProperty::Property) { int type = propertyType(); - if (type == QmlMetaProperty::Invalid) - category = QmlMetaProperty::InvalidProperty; - else if (type < QVariant::UserType) - category = QmlMetaProperty::Normal; + if (type == QVariant::Invalid) + return QmlMetaProperty::InvalidProperty; + else if ((uint)type < QVariant::UserType) + return QmlMetaProperty::Normal; else if (type == qMetaTypeId()) - category = QmlMetaProperty::Bindable; - else { - QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type); - switch(tc) { - case QmlMetaType::Object: - category = QmlMetaProperty::Object; - break; - case QmlMetaType::QmlList: - category = QmlMetaProperty::QmlList; - break; - case QmlMetaType::List: - category = QmlMetaProperty::List; - break; - case QmlMetaType::Unknown: - category = QmlMetaProperty::Normal; - break; - } - } + return QmlMetaProperty::Bindable; + else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived) + return QmlMetaProperty::Object; + else if (core.flags & QmlPropertyCache::Data::IsQmlList) + return QmlMetaProperty::QmlList; + else if (core.flags & QmlPropertyCache::Data::IsQList) + return QmlMetaProperty::List; + else + return QmlMetaProperty::Normal; + } else { + return QmlMetaProperty::InvalidProperty; } - return category; } /*! @@ -314,8 +297,21 @@ QmlMetaPropertyPrivate::propertyCategory() const */ const char *QmlMetaProperty::propertyTypeName() const { - if (!d->name.isEmpty() && d->object) { - return d->object->metaObject()->property(d->coreIdx).typeName(); + if (type() & ValueTypeProperty) { + + QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0; + QmlValueType *valueType = 0; + if (ep) valueType = ep->valueTypes[d->core.propType]; + else valueType = QmlValueTypeFactory::valueType(d->core.propType); + Q_ASSERT(valueType); + + const char *rv = valueType->metaObject()->property(d->valueTypeCoreIdx).typeName(); + + if (!ep) delete valueType; + + return rv; + } else if (d->object && type() & Property && d->core.isValid()) { + return d->object->metaObject()->property(d->core.coreIndex).typeName(); } else { return 0; } @@ -327,10 +323,13 @@ const char *QmlMetaProperty::propertyTypeName() const */ bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const { - return d->name == other.d->name && - d->signal.signature() == other.d->signal.signature() && - d->type == other.d->type && - d->object == other.d->object; + // category is intentially omitted here as it is generated + // from the other members + return d->object == other.d->object && + d->core == other.d->core && + d->valueTypeCoreIdx == other.d->valueTypeCoreIdx && + d->valueTypePropType == other.d->valueTypePropType && + d->attachedFunc == other.d->attachedFunc; } /*! @@ -344,18 +343,19 @@ int QmlMetaProperty::propertyType() const int QmlMetaPropertyPrivate::propertyType() const { - int rv = QVariant::Invalid; - - if (!name.isEmpty()) { - if (propType == (int)QVariant::LastType) - rv = qMetaTypeId(); + uint type = q->type(); + if (type & QmlMetaProperty::ValueTypeProperty) { + return valueTypePropType; + } else if (type & QmlMetaProperty::Attached) { + return qMetaTypeId(); + } else if (type & QmlMetaProperty::Property) { + if (core.propType == (int)QVariant::LastType) + return qMetaTypeId(); else - rv = propType; - } else if (attachedFunc) { - rv = qMetaTypeId(); - } - - return rv; + return core.propType; + } else { + return QVariant::Invalid; + } } /*! @@ -363,7 +363,16 @@ int QmlMetaPropertyPrivate::propertyType() const */ QmlMetaProperty::Type QmlMetaProperty::type() const { - return (Type)d->type; + if (d->core.flags & QmlPropertyCache::Data::IsFunction) + return SignalProperty; + else if (d->attachedFunc != -1) + return Attached; + else if (d->valueTypeCoreIdx != -1) + return (Type)(Property | ValueTypeProperty); + else if (d->core.isValid()) + return (Type)(Property | ((d->isDefaultProperty)?Default:0)); + else + return Invalid; } /*! @@ -395,17 +404,16 @@ QObject *QmlMetaProperty::object() const */ QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other) { - d->name = other.d->name; - d->signal = other.d->signal; d->context = other.d->context; - d->coreIdx = other.d->coreIdx; - d->valueTypeIdx = other.d->valueTypeIdx; - d->valueTypeId = other.d->valueTypeId; - d->type = other.d->type; - d->attachedFunc = other.d->attachedFunc; d->object = other.d->object; - d->propType = other.d->propType; - d->category = other.d->category; + + d->isDefaultProperty = other.d->isDefaultProperty; + d->core = other.d->core; + + d->valueTypeCoreIdx = other.d->valueTypeCoreIdx; + d->valueTypePropType = other.d->valueTypePropType; + + d->attachedFunc = other.d->attachedFunc; return *this; } @@ -414,12 +422,14 @@ QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other) */ bool QmlMetaProperty::isWritable() const { - if (propertyCategory() == List || propertyCategory() == QmlList) + QmlMetaProperty::PropertyCategory category = propertyCategory(); + + if (category == List || category == QmlList) return true; else if (type() & SignalProperty) return true; - else if (!d->name.isEmpty() && d->object) - return d->object->metaObject()->property(d->coreIdx).isWritable(); + else if (d->core.isValid() && d->object) + return d->object->metaObject()->property(d->core.coreIndex).isWritable(); else return false; } @@ -429,8 +439,8 @@ bool QmlMetaProperty::isWritable() const */ bool QmlMetaProperty::isDesignable() const { - if (!d->name.isEmpty() && d->object) - return d->object->metaObject()->property(d->coreIdx).isDesignable(); + if (type() & Property && d->core.isValid() && d->object) + return d->object->metaObject()->property(d->core.coreIndex).isDesignable(); else return false; } @@ -449,6 +459,7 @@ bool QmlMetaProperty::isValid() const */ QStringList QmlMetaProperty::properties(QObject *obj) { + // ### What is this used for? if (!obj) return QStringList(); @@ -467,7 +478,23 @@ QStringList QmlMetaProperty::properties(QObject *obj) */ QString QmlMetaProperty::name() const { - return d->name; + if (type() & ValueTypeProperty) { + QString rv = d->core.name + QLatin1String("."); + + QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0; + QmlValueType *valueType = 0; + if (ep) valueType = ep->valueTypes[d->core.propType]; + else valueType = QmlValueTypeFactory::valueType(d->core.propType); + Q_ASSERT(valueType); + + rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); + + if (!ep) delete valueType; + + return rv; + } else { + return d->core.name; + } } /*! @@ -476,13 +503,26 @@ QString QmlMetaProperty::name() const */ QMetaProperty QmlMetaProperty::property() const { - if (d->object) - return d->object->metaObject()->property(d->coreIdx); + if (type() & Property && d->core.isValid() && d->object) + return d->object->metaObject()->property(d->core.coreIndex); else return QMetaProperty(); } /*! + Return the QMetaMethod for this property if it is a SignalProperty, + otherwise returns an invalid QMetaMethod. +*/ +QMetaMethod QmlMetaProperty::method() const +{ + if (type() & SignalProperty && d->object) + return d->object->metaObject()->method(d->core.coreIndex); + else + return QMetaMethod(); +} + + +/*! Returns the binding associated with this property, or 0 if no binding exists. */ @@ -495,13 +535,13 @@ QmlAbstractBinding *QmlMetaProperty::binding() const if (!data) return 0; - if (!data->hasBindingBit(d->coreIdx)) + if (!data->hasBindingBit(d->core.coreIndex)) return 0; QmlAbstractBinding *binding = data->bindings; while (binding) { // ### This wont work for value types - if (binding->propertyIndex() == d->coreIdx) + if (binding->propertyIndex() == d->core.coreIndex) return binding; binding = binding->m_nextBinding; } @@ -527,11 +567,11 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const QmlDeclarativeData *data = QmlDeclarativeData::get(d->object, 0 != newBinding); - if (data && data->hasBindingBit(d->coreIdx)) { + if (data && data->hasBindingBit(d->core.coreIndex)) { QmlAbstractBinding *binding = data->bindings; while (binding) { // ### This wont work for value types - if (binding->propertyIndex() == d->coreIdx) { + if (binding->propertyIndex() == d->core.coreIndex) { binding->setEnabled(false); if (newBinding) @@ -594,15 +634,14 @@ QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const } if (expr) { - QmlBoundSignal *signal = new QmlBoundSignal(d->object, d->signal, - d->object); + QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object); return signal->setExpression(expr); } else { return 0; } } -void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name) +QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name) { const QMetaObject *mo = obj->metaObject(); @@ -613,12 +652,10 @@ void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name) int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); - if (methodName == name) { - signal = method; - coreIdx = ii; - return; - } + if (methodName == name) + return method; } + return QMetaMethod(); } QObject *QmlMetaPropertyPrivate::attachedObject() const @@ -643,7 +680,7 @@ QVariant QmlMetaProperty::read() const for (int ii = 0; ii < children.count(); ++ii) { QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == d->coreIdx) + if (sig && sig->index() == d->core.coreIndex) return sig->expression()->expression(); } @@ -662,7 +699,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) for (int ii = 0; ii < children.count(); ++ii) { QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == coreIdx) { + if (sig && sig->index() == core.coreIndex) { if (expr.isEmpty()) { sig->disconnect(); sig->deleteLater(); @@ -675,12 +712,13 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) if (!expr.isEmpty()) { // XXX scope - (void *)new QmlBoundSignal(qmlContext(object), expr, object, signal, object); + (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object); } } QVariant QmlMetaPropertyPrivate::readValueProperty() { + uint type = q->type(); if (type & QmlMetaProperty::Attached) { return QVariant::fromValue(attachedObject()); @@ -689,22 +727,21 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0; QmlValueType *valueType = 0; - if (ep) - valueType = ep->valueTypes[valueTypeId]; - else - valueType = QmlValueTypeFactory::valueType(valueTypeId); + if (ep) valueType = ep->valueTypes[core.propType]; + else valueType = QmlValueTypeFactory::valueType(core.propType); Q_ASSERT(valueType); - valueType->read(object, coreIdx); + valueType->read(object, core.coreIndex); + QVariant rv = - valueType->metaObject()->property(valueTypeIdx).read(valueType); - if (!ep) - delete valueType; + valueType->metaObject()->property(valueTypeCoreIdx).read(valueType); + + if (!ep) delete valueType; return rv; } else { - return object->metaObject()->property(coreIdx).read(object.data()); + return object->metaObject()->property(core.coreIndex).read(object.data()); } } @@ -712,40 +749,49 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlMetaProperty::WriteSource source) { - QObject *object = this->object; - int coreIdx = this->coreIdx; - - QmlValueType *writeBack = 0; - QObject *writeBackObj = 0; - int writeBackIdx = -1; - bool deleteWriteBack = false; - // Remove any existing bindings on this property if (source != QmlMetaProperty::Binding) delete q->setBinding(0); + uint type = q->type(); if (type & QmlMetaProperty::ValueTypeProperty) { - QmlEnginePrivate *ep = context?static_cast(QObjectPrivate::get(context->engine())):0; + QmlEnginePrivate *ep = + context?static_cast(QObjectPrivate::get(context->engine())):0; + QmlValueType *writeBack = 0; if (ep) { - writeBack = ep->valueTypes[valueTypeId]; + writeBack = ep->valueTypes[core.propType]; } else { - writeBack = QmlValueTypeFactory::valueType(valueTypeId); - deleteWriteBack = true; + writeBack = QmlValueTypeFactory::valueType(core.propType); } - writeBackObj = this->object; - writeBackIdx = this->coreIdx; - writeBack->read(writeBackObj, writeBackIdx); - object = writeBack; - coreIdx = valueTypeIdx; + writeBack->read(object, core.coreIndex); + + QmlPropertyCache::Data data = core; + data.coreIndex = valueTypeCoreIdx; + data.propType = valueTypePropType; + write(writeBack, data, value, context); + + writeBack->write(object, core.coreIndex); + if (!ep) delete writeBack; + + } else { + + write(object, core, value, context); + } +} - QMetaProperty prop = object->metaObject()->property(coreIdx); +void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property, + const QVariant &value, QmlContext *context) +{ + int coreIdx = property.coreIndex; - if (prop.isEnumType()) { + if (property.flags & QmlPropertyCache::Data::IsEnumType) { + QMetaProperty prop = object->metaObject()->property(property.coreIndex); QVariant v = value; - if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles + // Enum values come through the script engine as doubles + if (value.type() == QVariant::Double) { double integral; double fractional = modf(value.toDouble(), &integral); if (qFuzzyCompare(fractional, (double)0.0)) @@ -753,19 +799,36 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, } prop.write(object, v); - if (writeBack) { - writeBack->write(writeBackObj, writeBackIdx); - if (deleteWriteBack) delete writeBack; - } return; } - int t = propertyType(); + int t = property.propType; int vt = value.userType(); - int category = propertyCategory(); - if (vt == t - && t != QVariant::Url) { // always resolve relative urls + if (t == QVariant::Url) { + + QUrl u; + bool found = false; + if (vt == QVariant::Url) { + u = value.toUrl(); + found = true; + } else if (vt == QVariant::ByteArray) { + u = QUrl(QLatin1String(value.toByteArray())); + found = true; + } else if (vt == QVariant::String) { + u = QUrl(value.toString()); + found = true; + } + + if (found) { + if (context && u.isRelative() && !u.isEmpty()) + u = context->baseUrl().resolved(u); + void *a[1]; + a[0] = &u; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + } + + } else if (vt == t) { void *a[1]; a[0] = (void *)value.constData(); @@ -773,9 +836,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, } else if (qMetaTypeId() == t) { - prop.write(object, value); + void *a[1]; + a[0] = (void *)&value; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); - } else if (category == QmlMetaProperty::Object) { + } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) { QObject *o = QmlMetaType::toQObject(value); @@ -802,9 +867,10 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, } - } else if (category == QmlMetaProperty::List) { + } else if (property.flags & QmlPropertyCache::Data::IsQList) { int listType = QmlMetaType::listType(t); + QMetaProperty prop = object->metaObject()->property(property.coreIndex); if (value.userType() == qMetaTypeId >()) { const QList &list = @@ -822,9 +888,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlMetaType::clear(listVar); QmlMetaType::append(listVar, value); } - } else if (category == QmlMetaProperty::QmlList) { + + } else if (property.flags & QmlPropertyCache::Data::IsQmlList) { // XXX - optimize! + QMetaProperty prop = object->metaObject()->property(property.coreIndex); QVariant list = prop.read(object); QmlPrivate::ListInterface *li = *(QmlPrivate::ListInterface **)list.constData(); @@ -854,118 +922,25 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, void *d = (void *)&obj; li->append(d); } - } else if (category == QmlMetaProperty::Normal) { - - bool found = false; - switch(t) { - case QVariant::Double: - { - double d; - if (vt == QVariant::Int) { - d = value.toInt(); - found = true; - } else if (vt == QVariant::UInt) { - d = value.toUInt(); - found = true; - } - - if (found) { - void *a[1]; - a[0] = &d; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - } - } - break; - - case QVariant::Int: - { - int i; - if (vt == QVariant::Double) { - i = (int)value.toDouble(); - found = true; - } else if (vt == QVariant::UInt) { - i = (int)value.toUInt(); - found = true; - } - - if (found) { - void *a[1]; - a[0] = &i; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - } - } - break; - - case QVariant::String: - { - QString s; - if (vt == QVariant::ByteArray) { - s = QLatin1String(value.toByteArray()); - found = true; - } - - if (found) { - void *a[1]; - a[0] = &s; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); - } - } - break; - - case QVariant::Url: - { - QUrl u; - if (vt == QVariant::Url) { - u = value.toUrl(); - found = true; - } else if (vt == QVariant::ByteArray) { - u = QUrl(QLatin1String(value.toByteArray())); - found = true; - } else if (vt == QVariant::String) { - u = QUrl(value.toString()); - found = true; - } + } else { + Q_ASSERT(vt != t); - if (found) { - if (context && u.isRelative() && !u.isEmpty()) - u = context->baseUrl().resolved(u); + QVariant v = value; + if (v.convert((QVariant::Type)t)) { + void *a[1]; + a[0] = (void *)v.constData(); + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) { + QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t); + if (con) { + QVariant v = con(value.toString()); + if (v.userType() == t) { void *a[1]; - a[0] = &u; - QMetaObject::metacall(object, - QMetaObject::WriteProperty, - coreIdx, a); + a[0] = (void *)v.constData(); + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } - } - break; - - - default: - { - if ((uint)t >= QVariant::UserType && vt == QVariant::String) { - QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t); - if (con) { - QVariant v = con(value.toString()); - prop.write(object, v); - found = true; - } - } - } - break; } - if (!found) - prop.write(object, value); - } - - if (writeBack) { - writeBack->write(writeBackObj, writeBackIdx); - if (deleteWriteBack) delete writeBack; } } @@ -986,7 +961,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const d->writeSignalProperty(value); - } else if (d->coreIdx != -1) { + } else if (d->core.isValid()) { d->writeValueProperty(value, source); @@ -999,7 +974,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const bool QmlMetaProperty::hasChangedNotifier() const { if (type() & Property && !(type() & Attached) && d->object) { - return d->object->metaObject()->property(d->coreIdx).hasNotifySignal(); + return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal(); } return false; } @@ -1030,7 +1005,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const if (!(type() & Property) || (type() & Attached) || !d->object) return false; - QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); + QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex); if (prop.hasNotifySignal()) { return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection); } else { @@ -1051,7 +1026,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const if (!(type() & Property) || (type() & Attached) || !d->object) return false; - QMetaProperty prop = d->object->metaObject()->property(d->coreIdx); + QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex); if (prop.hasNotifySignal()) { QByteArray signal(QByteArray("2") + prop.notifySignal().signature()); return QObject::connect(d->object, signal.constData(), dest, slot); @@ -1065,7 +1040,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const */ int QmlMetaProperty::coreIndex() const { - return d->coreIdx; + return d->core.coreIndex; } Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes); @@ -1080,17 +1055,17 @@ quint32 QmlMetaProperty::save() const if (type() & Attached) { rv = d->attachedFunc; } else if (type() != Invalid) { - rv = d->coreIdx; + rv = d->core.coreIndex; } Q_ASSERT(rv <= 0x7FF); Q_ASSERT(type() <= 0x3F); - Q_ASSERT(d->valueTypeIdx <= 0x7F); + Q_ASSERT(d->valueTypeCoreIdx <= 0x7F); rv |= (type() << 18); if (type() & ValueTypeProperty) - rv |= (d->valueTypeIdx << 11); + rv |= (d->valueTypeCoreIdx << 11); return rv; } @@ -1131,12 +1106,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->context = ctxt; id &= 0xFFFFFF; - d->type = id >> 18; + uint type = id >> 18; id &= 0xFFFF; - if (d->type & Attached) { + if (type & Attached) { d->attachedFunc = id; - } else if (d->type & ValueTypeProperty) { + } else if (type & ValueTypeProperty) { int coreIdx = id & 0x7FF; int valueTypeIdx = id >> 11; @@ -1147,46 +1122,31 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx)); - d->name = QLatin1String(p2.name()); - d->propType = p2.userType(); - d->coreIdx = coreIdx; - d->valueTypeIdx = valueTypeIdx; - d->valueTypeId = p.type(); - - } else if (d->type & Property) { + d->core.load(p); + d->valueTypeCoreIdx = valueTypeIdx; + d->valueTypePropType = p.userType(); + } else if (type & Property) { QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0; - d->coreIdx = id; - if (cache) { QmlPropertyCache::Data *data = cache->property(id); - d->propType = data->propType; - d->name = data->name; + if (data) d->core = *data; } else { QMetaProperty p(obj->metaObject()->property(id)); - d->name = QLatin1String(p.name()); - d->propType = p.userType(); + d->core.load(p); } - } else if (d->type & SignalProperty) { - d->signal = obj->metaObject()->method(id); - d->coreIdx = id; + } else if (type & SignalProperty) { + + QMetaMethod method = obj->metaObject()->method(id); + d->core.load(method); } else { *this = QmlMetaProperty(); } } /*! - Return the QMetaMethod for this property if it is a SignalProperty, - otherwise returns an invalid QMetaMethod. -*/ -QMetaMethod QmlMetaProperty::method() const -{ - return d->signal; -} - -/*! \internal Creates a QmlMetaProperty for the property \a name of \a obj. Unlike @@ -1213,17 +1173,11 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); if (idx == -1) return QmlMetaProperty(); + QMetaProperty vtProp = typeObject->metaObject()->property(idx); - QmlMetaProperty p; - p.d->name = pathName + QLatin1String(".") + path.last(); - p.d->context = 0; - p.d->coreIdx = prop.coreIndex(); - p.d->valueTypeIdx = idx; - p.d->valueTypeId = prop.propertyType(); - p.d->type = QmlMetaProperty::ValueTypeProperty | - QmlMetaProperty::Property; - p.d->object = obj; - p.d->propType = typeObject->metaObject()->property(idx).userType(); + QmlMetaProperty p = prop; + p.d->valueTypeCoreIdx = idx; + p.d->valueTypePropType = vtProp.userType(); return p; } diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 3193aaf..729236b 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -54,7 +54,8 @@ // #include "qmlmetaproperty.h" -#include "private/qobject_p.h" +#include +#include QT_BEGIN_NAMESPACE @@ -63,36 +64,34 @@ class QmlMetaPropertyPrivate { public: QmlMetaPropertyPrivate() - : q(0), context(0), coreIdx(-1), valueTypeIdx(-1), valueTypeId(0), - type(QmlMetaProperty::Invalid), attachedFunc(-1), - object(0), propType(-1), category(QmlMetaProperty::Unknown) {} + : q(0), context(0), object(0), isDefaultProperty(false), valueTypeCoreIdx(-1), + valueTypePropType(0), attachedFunc(-1) {} + QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other) - : q(0), name(other.name), signal(other.signal), context(other.context), - coreIdx(other.coreIdx), valueTypeIdx(other.valueTypeIdx), - valueTypeId(other.valueTypeId), type(other.type), - attachedFunc(other.attachedFunc), object(other.object), - propType(other.propType), category(other.category) {} + : q(0), context(other.context), object(other.object), + isDefaultProperty(other.isDefaultProperty), core(other.core), + valueTypeCoreIdx(other.valueTypeCoreIdx), + valueTypePropType(other.valueTypePropType), attachedFunc(other.attachedFunc) {} QmlMetaProperty *q; - - QString name; - QMetaMethod signal; QmlContext *context; - int coreIdx; - int valueTypeIdx; - int valueTypeId; - uint type; - int attachedFunc; QGuard object; - int propType; - mutable QmlMetaProperty::PropertyCategory category; + bool isDefaultProperty; + QmlPropertyCache::Data core; + + // Describes the "virtual" value-type sub-property. + int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper + int valueTypePropType; // The QVariant::Type of access property on the value type wrapper + + // The attached property accessor + int attachedFunc; void initProperty(QObject *obj, const QString &name); void initDefault(QObject *obj); QObject *attachedObject() const; - void findSignalInt(QObject *, const QString &); + QMetaMethod findSignal(QObject *, const QString &); int propertyType() const; QmlMetaProperty::PropertyCategory propertyCategory() const; @@ -101,6 +100,7 @@ public: QVariant readValueProperty(); void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); + static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); static quint32 saveValueType(int, int); static quint32 saveProperty(int); diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 95b819a..7d234fd 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -40,10 +40,48 @@ ****************************************************************************/ #include "qmlpropertycache_p.h" -#include "qmlengine_p.h" +#include +#include QT_BEGIN_NAMESPACE +void QmlPropertyCache::Data::load(const QMetaProperty &p) +{ + propType = p.userType(); + coreIndex = p.propertyIndex(); + notifyIndex = p.notifySignalIndex(); + name = QLatin1String(p.name()); + + if (p.isConstant()) + flags |= Data::IsConstant; + + if (propType == qMetaTypeId()) { + flags |= Data::IsQmlBinding; + } else if (p.isEnumType()) { + flags |= Data::IsEnumType; + } else { + QmlMetaType::TypeCategory cat = QmlMetaType::typeCategory(propType); + if (cat == QmlMetaType::Object) + flags |= Data::IsQObjectDerived; + else if (cat == QmlMetaType::List) + flags |= Data::IsQList; + else if (cat == QmlMetaType::QmlList) + flags |= Data::IsQmlList; + } +} + +void QmlPropertyCache::Data::load(const QMetaMethod &m) +{ + name = QLatin1String(m.signature()); + int parenIdx = name.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + name = name.left(parenIdx); + + coreIndex = m.methodIndex(); + flags |= Data::IsFunction; +} + + QmlPropertyCache::QmlPropertyCache() { } @@ -83,15 +121,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject QScriptDeclarativeClass::PersistentIdentifier *data = enginePriv->objectClass->createPersistentIdentifier(propName); - data->propType = p.userType(); - data->coreIndex = ii; - data->notifyIndex = p.notifySignalIndex(); - data->name = propName; - - if (p.isConstant()) - data->flags |= Data::IsConstant; - if (QmlMetaType::isObject(data->propType)) - data->flags |= Data::IsQObjectDerived; + data->load(p); cache->indexCache[ii] = data; @@ -118,12 +148,13 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject QScriptDeclarativeClass::PersistentIdentifier *data = enginePriv->objectClass->createPersistentIdentifier(methodName); + + data->load(m); + cache->stringCache.insert(methodName, data); cache->identifierCache.insert(data->identifier, data); data->addref(); data->addref(); - - data->flags |= Data::IsFunction; } return cache; diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 21c8ef3..149d2a0 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -69,18 +69,40 @@ public: struct Data { inline Data(); + inline bool operator==(const Data &); - enum Flag { IsFunction = 0x00000001, + enum Flag { + // Can apply to all properties, except IsFunction + IsConstant = 0x00000004, + + // These are mutually exclusive + IsFunction = 0x00000001, IsQObjectDerived = 0x00000002, - IsConstant = 0x00000004 }; + IsEnumType = 0x00000008, + IsQmlList = 0x00000010, + IsQList = 0x00000020, + IsQmlBinding = 0x00000040 + }; Q_DECLARE_FLAGS(Flags, Flag) + bool isValid() const { return coreIndex != -1; } + Flags flags; int propType; int coreIndex; int notifyIndex; QString name; + + void load(const QMetaProperty &); + void load(const QMetaMethod &); + }; + +#if 0 + struct ValueTypeData { + int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper + int valueTypePropType; // The QVariant::Type of access property on the value type wrapper }; +#endif static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); @@ -106,6 +128,15 @@ QmlPropertyCache::Data::Data() { } +bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other) +{ + return flags == other.flags && + propType == other.propType && + coreIndex == other.coreIndex && + notifyIndex == other.notifyIndex && + name == other.name; +} + QmlPropertyCache::Data * QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const { -- cgit v0.12 From 361a605e9269f3072c1f5597a8db0622cf3b116b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 1 Oct 2009 17:36:35 +1000 Subject: Read/write property directly from QmlObjectScriptClass --- src/declarative/qml/qmlcontext.cpp | 1 - src/declarative/qml/qmlobjectscriptclass.cpp | 110 +++++++++------------------ src/declarative/qml/qmlobjectscriptclass_p.h | 2 + src/declarative/qml/qmlpropertycache.cpp | 37 +++++++++ src/declarative/qml/qmlpropertycache_p.h | 16 ++-- 5 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 1c9d177..5e74d1a 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -386,7 +386,6 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx, notifyIndex = q->metaObject()->methodCount(); } - propertyNames->add(name, idx); idValues[idx].priv = this; idValues[idx] = obj; } diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 0ae1809..28a808a 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -149,20 +149,19 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, } if (cache) { - QmlPropertyCache::Data *property = cache->property(name); - if (!property) return 0; - - if (flags == QScriptClass::HandlesReadAccess) { - lastData = property; - return QScriptClass::HandlesReadAccess; - } else if (property->propType > 0 && property->propType < QVariant::UserType) { - lastData = property; - return flags; - } + lastData = cache->property(name); + } else { + local = QmlPropertyCache::create(obj->metaObject(), toString(name)); + if (local.isValid()) + lastData = &local; } - // Fallback - return QmlEnginePrivate::get(engine)->queryObject(toString(name), &m_id, obj); + if (!lastData) return 0; + + QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess; + if (lastData->flags & QmlPropertyCache::Data::IsWritable) + rv |= QScriptClass::HandlesWriteAccess; + return rv; } QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifier &name) @@ -175,35 +174,31 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name if (name == m_destroyId->identifier) return m_destroy; + Q_ASSERT(lastData); + Q_ASSERT(obj); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); - if (!obj) { - return QScriptValue(); - } else if (lastData) { + if (lastData->flags & QmlPropertyCache::Data::IsFunction) { + // ### Optimize + QScriptValue sobj = scriptEngine->newQObject(obj); + return sobj.property(toString(name)); + } else { + + QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); + if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { + enginePriv->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + } - if (lastData->flags & QmlPropertyCache::Data::IsFunction) { - // ### Optimize - QScriptValue sobj = scriptEngine->newQObject(obj); - return sobj.property(toString(name)); + if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { + QObject *rv = *(QObject **)var.constData(); + return newQObject(rv); } else { - QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); - if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { - enginePriv->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, - lastData->notifyIndex); - } - - if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { - QObject *rv = *(QObject **)var.constData(); - return newQObject(rv); - } else { - return qScriptValueFromValue(scriptEngine, var); - } + return qScriptValueFromValue(scriptEngine, var); } - } else { - return QmlEnginePrivate::get(engine)->propertyObject(toString(name), obj, m_id); } } @@ -219,51 +214,16 @@ void QmlObjectScriptClass::setProperty(QObject *obj, const QScriptValue &value) { Q_UNUSED(name); - Q_UNUSED(object); + + Q_ASSERT(obj); + Q_ASSERT(lastData); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); - if (!obj) { - return; - } else if (lastData) { - switch (lastData->propType) { - case 1: - { - bool b = value.toBoolean(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - case 2: - { - int b = value.toInteger(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - case 6: - { - double b = value.toNumber(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - default: - { - QMetaProperty p = obj->metaObject()->property(lastData->coreIndex); - p.write(obj, value.toVariant()); - } - } - } else { - QmlEnginePrivate::get(engine)->setPropertyObject(value, m_id); - } + // ### Can well known types be optimized? + QVariant v = QmlScriptClass::toVariant(engine, value); + QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context()); } QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok) diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index c25718c..f126192 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -86,6 +86,8 @@ protected: private: uint m_id; QmlPropertyCache::Data *lastData; + QmlPropertyCache::Data local; + struct Dummy {}; PersistentIdentifier *m_destroyId; QScriptValue m_destroy; diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 7d234fd..cc4c2ab 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -54,6 +54,8 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) if (p.isConstant()) flags |= Data::IsConstant; + if (p.isWritable()) + flags |= Data::IsWritable; if (propType == qMetaTypeId()) { flags |= Data::IsQmlBinding; @@ -100,6 +102,41 @@ QmlPropertyCache::~QmlPropertyCache() (*iter)->release(); } +QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, + const QString &property) +{ + Q_ASSERT(metaObject); + + QmlPropertyCache::Data rv; + + int propCount = metaObject->propertyCount(); + for (int ii = propCount - 1; ii >= 0; --ii) { + QMetaProperty p = metaObject->property(ii); + QString propName = QLatin1String(p.name()); + if (propName == property) { + rv.load(p); + return rv; + } + } + + int methodCount = metaObject->methodCount(); + for (int ii = methodCount - 1; ii >= 0; --ii) { + QMetaMethod m = metaObject->method(ii); + QString methodName = QLatin1String(m.signature()); + + int parenIdx = methodName.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + methodName = methodName.left(parenIdx); + + if (methodName == property) { + rv.load(m); + return rv; + } + } + + return rv; +} + // ### Optimize - check engine for the parent meta object etc. QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject) { diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 149d2a0..82b8737 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -73,15 +73,16 @@ public: enum Flag { // Can apply to all properties, except IsFunction - IsConstant = 0x00000004, + IsConstant = 0x00000001, + IsWritable = 0x00000002, // These are mutually exclusive - IsFunction = 0x00000001, - IsQObjectDerived = 0x00000002, - IsEnumType = 0x00000008, - IsQmlList = 0x00000010, - IsQList = 0x00000020, - IsQmlBinding = 0x00000040 + IsFunction = 0x00000004, + IsQObjectDerived = 0x00000008, + IsEnumType = 0x00000010, + IsQmlList = 0x00000020, + IsQList = 0x00000040, + IsQmlBinding = 0x00000080 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -105,6 +106,7 @@ public: #endif static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); + static Data create(const QMetaObject *, const QString &); inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; Data *property(const QString &) const; -- cgit v0.12 From 02a248c9c57714d4ad1ba775d9e60a7f286f10c6 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 1 Oct 2009 18:52:53 +1000 Subject: Prevent writes to the global object Also add toString() method to qobjects --- demos/declarative/samegame/content/samegame.js | 28 ++++---- src/declarative/qml/qml.pri | 6 +- src/declarative/qml/qmlengine.cpp | 16 +++-- src/declarative/qml/qmlengine_p.h | 2 + src/declarative/qml/qmlglobalscriptclass.cpp | 94 ++++++++++++++++++++++++++ src/declarative/qml/qmlglobalscriptclass_p.h | 81 ++++++++++++++++++++++ src/declarative/qml/qmlobjectscriptclass.cpp | 83 +++++++++++++---------- src/declarative/qml/qmlobjectscriptclass_p.h | 8 +++ 8 files changed, 260 insertions(+), 58 deletions(-) create mode 100644 src/declarative/qml/qmlglobalscriptclass.cpp create mode 100644 src/declarative/qml/qmlglobalscriptclass_p.h diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js index 4a9179b..09057eb 100755 --- a/demos/declarative/samegame/content/samegame.js +++ b/demos/declarative/samegame/content/samegame.js @@ -24,7 +24,7 @@ function timeStr(msecs) { function initBoard() { - for(i = 0; i= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0) return; if(board[index(xIdx, yIdx)] == null) @@ -105,14 +105,14 @@ function floodFill(xIdx,yIdx,type) function shuffleDown() { //Fall down - for(xIdx=0; xIdx=0; yIdx--){ + for(var xIdx=0; xIdx=0; yIdx--){ if(board[index(xIdx,yIdx)] == null){ fallDist += 1; }else{ if(fallDist > 0){ - obj = board[index(xIdx,yIdx)]; + var obj = board[index(xIdx,yIdx)]; obj.targetY += fallDist * tileSize; board[index(xIdx,yIdx+fallDist)] = obj; board[index(xIdx,yIdx)] = null; @@ -143,8 +143,8 @@ function shuffleDown() function victoryCheck() { //awards bonuses for no tiles left - deservesBonus = true; - for(xIdx=maxX-1; xIdx>=0; xIdx--) + var deservesBonus = true; + for(var xIdx=maxX-1; xIdx>=0; xIdx--) if(board[index(xIdx, maxY - 1)] != null) deservesBonus = false; if(deservesBonus) @@ -166,7 +166,7 @@ function floodMoveCheck(xIdx, yIdx, type) return false; if(board[index(xIdx, yIdx)] == null) return false; - myType = board[index(xIdx, yIdx)].type; + var myType = board[index(xIdx, yIdx)].type; if(type == myType) return true; return floodMoveCheck(xIdx + 1, yIdx, myType) || @@ -174,7 +174,7 @@ function floodMoveCheck(xIdx, yIdx, type) } function createBlock(xIdx,yIdx){ - if(component==null) + if(component==null) component = createComponent(tileSrc); // Note that we don't wait for the component to become ready. This will @@ -182,7 +182,7 @@ function createBlock(xIdx,yIdx){ // not be ready immediately. There is a statusChanged signal on the // component you could use if you want to wait to load remote files. if(component.isReady){ - dynamicObject = component.createObject(); + var dynamicObject = component.createObject(); if(dynamicObject == null){ print("error creating block"); print(component.errorsString()); diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 1a6dad3..eb761e3 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -38,7 +38,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlpropertycache.cpp \ qml/qmlintegercache.cpp \ qml/qmlobjectscriptclass.cpp \ - qml/qmlcontextscriptclass.cpp + qml/qmlcontextscriptclass.cpp \ + qml/qmlglobalscriptclass.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -94,7 +95,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlpropertycache_p.h \ qml/qmlintegercache_p.h \ qml/qmlobjectscriptclass_p.h \ - qml/qmlcontextscriptclass_p.h + qml/qmlcontextscriptclass_p.h \ + qml/qmlglobalscriptclass_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index d680fa1..4afd245 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef QT_SCRIPTTOOLS_LIB #include @@ -156,7 +157,7 @@ static QString userLocalDataPath(const QString& app) QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) : rootContext(0), currentExpression(0), - isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), + isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0), nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), scriptEngine(this), rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1) { @@ -183,6 +184,14 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) qtObject.setProperty(QLatin1String("lighter"), scriptEngine.newFunction(QmlEnginePrivate::lighter, 1)); qtObject.setProperty(QLatin1String("darker"), scriptEngine.newFunction(QmlEnginePrivate::darker, 1)); qtObject.setProperty(QLatin1String("tint"), scriptEngine.newFunction(QmlEnginePrivate::tint, 2)); + + scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"), + scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1)); + scriptEngine.globalObject().setProperty(QLatin1String("createComponent"), + scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1)); + + //scriptEngine.globalObject().setScriptClass(new QmlGlobalScriptClass(&scriptEngine)); + globalClass = new QmlGlobalScriptClass(&scriptEngine); } QmlEnginePrivate::~QmlEnginePrivate() @@ -250,11 +259,6 @@ void QmlEnginePrivate::init() } #endif - scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"), - scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1)); - scriptEngine.globalObject().setProperty(QLatin1String("createComponent"), - scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1)); - if (QCoreApplication::instance()->thread() == q->thread() && QmlEngineDebugServer::isDebuggingEnabled()) { qmlEngineDebugServer(); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 764cc6c..231388d 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -151,6 +151,8 @@ public: QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; QmlTypeNameScriptClass *typeNameClass; + // Global script class + QScriptClass *globalClass; // Used by DOM Core 3 API QScriptClass *nodeListClass; QScriptClass *namedNodeMapClass; diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp new file mode 100644 index 0000000..0ade5ee --- /dev/null +++ b/src/declarative/qml/qmlglobalscriptclass.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlglobalscriptclass_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/* + Used to prevent any writes to the global object. +*/ +QmlGlobalScriptClass::QmlGlobalScriptClass(QScriptEngine *engine) +: QScriptClass(engine) +{ + QScriptValue v = engine->newObject(); + globalObject = engine->globalObject(); + + QScriptValueIterator iter(globalObject); + while (iter.hasNext()) { + iter.next(); + v.setProperty(iter.scriptName(), iter.value()); + } + + v.setScriptClass(this); + engine->setGlobalObject(v); +} + +QScriptClass::QueryFlags +QmlGlobalScriptClass::queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id) +{ + return HandlesReadAccess | HandlesWriteAccess; +} + +QScriptValue +QmlGlobalScriptClass::property(const QScriptValue &object, + const QScriptString &name, + uint id) +{ + return engine()->undefinedValue(); +} + +void QmlGlobalScriptClass::setProperty(QScriptValue &object, + const QScriptString &name, + uint id, const QScriptValue &value) +{ + QString error = QLatin1String("Invalid write to global property \"") + + name.toString() + QLatin1String("\""); + engine()->currentContext()->throwError(error); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmlglobalscriptclass_p.h b/src/declarative/qml/qmlglobalscriptclass_p.h new file mode 100644 index 0000000..1b58f1e --- /dev/null +++ b/src/declarative/qml/qmlglobalscriptclass_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 QMLGLOBALSCRIPTCLASS_P_H +#define QMLGLOBALSCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QmlGlobalScriptClass : public QScriptClass +{ +public: + QmlGlobalScriptClass(QScriptEngine *); + + 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); + +private: + QScriptValue globalObject; +}; + +QT_END_NAMESPACE + +#endif // QMLGLOBALSCRIPTCLASS_P_H diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 28a808a..bb5f191 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -51,40 +51,6 @@ struct ObjectData { QGuard object; }; -static QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine) -{ - QObject* obj = context->thisObject().data().toQObject(); - QString ret = QLatin1String("Qml Object, "); - if(obj){ - //###Should this be designer or developer details? Dev for now. - //TODO: Can we print the id too? - ret += QLatin1String("\""); - ret += obj->objectName(); - ret += QLatin1String("\" "); - ret += QLatin1String(obj->metaObject()->className()); - ret += QLatin1String("(0x"); - ret += QString::number((quintptr)obj,16); - ret += QLatin1String(")"); - }else{ - ret += QLatin1String("null"); - } - return engine->newVariant(ret); -} - -static QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine) -{ - QObject* obj = context->thisObject().toQObject(); - if(obj){ - int delay = 0; - if(context->argumentCount() > 0) - delay = context->argument(0).toInt32(); - obj->deleteLater(); - //### Should this be delayed as well? - context->thisObject().setData(QScriptValue(engine, 0)); - } - return engine->nullValue(); -} - /* The QmlObjectScriptClass handles property access for QObjects via QtScript. It is also used to provide a more useful API in @@ -97,8 +63,10 @@ QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) engine = bindEngine; QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); - m_destroy = scriptEngine->newFunction(QmlObjectDestroy); + m_destroy = scriptEngine->newFunction(destroy); m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); + m_toString = scriptEngine->newFunction(tostring); + m_toStringId = createPersistentIdentifier(QLatin1String("toString")); } QmlObjectScriptClass::~QmlObjectScriptClass() @@ -132,7 +100,8 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, Q_UNUSED(flags); lastData = 0; - if (name == m_destroyId->identifier) + if (name == m_destroyId->identifier || + name == m_toStringId->identifier) return QScriptClass::HandlesReadAccess; if (!obj) @@ -173,6 +142,8 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name { if (name == m_destroyId->identifier) return m_destroy; + else if (name == m_toStringId->identifier) + return m_toString; Q_ASSERT(lastData); Q_ASSERT(obj); @@ -240,4 +211,44 @@ void QmlObjectScriptClass::destroyed(const Object &object) delete data; } +QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *engine) +{ + QObject* obj = context->thisObject().toQObject(); + + QString ret; + if(obj){ + QString objectName = obj->objectName(); + + ret += QLatin1String(obj->metaObject()->className()); + ret += QLatin1String("(0x"); + ret += QString::number((quintptr)obj,16); + + if (!objectName.isEmpty()) { + ret += QLatin1String(", \""); + ret += objectName; + ret += QLatin1String("\""); + } + + ret += QLatin1String(")"); + }else{ + ret += QLatin1String("null"); + } + return QScriptValue(ret); +} + +QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine) +{ + QObject* obj = context->thisObject().toQObject(); + if(obj){ + int delay = 0; + if(context->argumentCount() > 0) + delay = context->argument(0).toInt32(); + obj->deleteLater(); + //### Should this be delayed as well? + context->thisObject().setData(QScriptValue(engine, 0)); + } + return engine->nullValue(); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index f126192..cd67fac 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE class QmlEngine; +class QScriptContext; +class QScriptEngine; class QmlObjectScriptClass : public QScriptDeclarativeClass { public: @@ -90,7 +92,13 @@ private: struct Dummy {}; PersistentIdentifier *m_destroyId; + PersistentIdentifier *m_toStringId; QScriptValue m_destroy; + QScriptValue m_toString; + + static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine); + static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine); + QmlEngine *engine; }; -- cgit v0.12 From 15498e4c5990e934e5f2a3ee27f71c020e277e56 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 10:04:35 +1000 Subject: Only start timer if it isn't already active --- src/corelib/animation/qabstractanimation.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 6bbd801..4c68ee7 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -231,7 +231,8 @@ void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation) Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer); QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true; animationsToStart << animation; - startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); + if (!startStopAnimationTimer.isActive()) + startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); } void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) @@ -250,7 +251,8 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) } else { animationsToStart.removeOne(animation); } - QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false; + if (!startStopAnimationTimer.isActive()) + startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); } void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) -- cgit v0.12 From b3605d7f45c1cdb61bbd2a572e58bd29aaea6956 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 10:49:14 +1000 Subject: API changes --- src/script/bridge/qscriptdeclarativeclass.cpp | 107 ++++++++++++++++++-------- src/script/bridge/qscriptdeclarativeclass_p.h | 33 ++++---- 2 files changed, 87 insertions(+), 53 deletions(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index c017e13..371a3c3 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -51,39 +51,38 @@ QT_BEGIN_NAMESPACE -class QScriptDeclarativeClassPrivate +QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier() { -public: - QScriptDeclarativeClassPrivate() {} - - QScriptEngine *engine; - QScriptDeclarativeClass *q_ptr; -}; + new (&d) JSC::Identifier(); +} -void QScriptDeclarativeClass::destroyPersistentIdentifier(void **d) +QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier() { - ((JSC::Identifier *)d)->JSC::Identifier::~Identifier(); + ((JSC::Identifier &)d).JSC::Identifier::~Identifier(); } -void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, const QString &str) +QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other) { - QScriptEnginePrivate *p = - static_cast(QObjectPrivate::get(d_ptr->engine)); - JSC::ExecState* exec = p->currentFrame; + identifier = other.identifier; + new (&d) JSC::Identifier((JSC::Identifier &)(other.d)); +} - new (d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); - *i = (Identifier)((JSC::Identifier *)d)->ustring().rep(); +QScriptDeclarativeClass::PersistentIdentifier & +QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other) +{ + identifier = other.identifier; + ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d); + return *this; } -void QScriptDeclarativeClass::initPersistentIdentifier(void **d, Identifier *i, const Identifier &id) +class QScriptDeclarativeClassPrivate { - QScriptEnginePrivate *p = - static_cast(QObjectPrivate::get(d_ptr->engine)); - JSC::ExecState* exec = p->currentFrame; +public: + QScriptDeclarativeClassPrivate() {} - new (d) JSC::Identifier(exec, (JSC::UString::Rep *)id); - *i = id; -} + QScriptEngine *engine; + QScriptDeclarativeClass *q_ptr; +}; QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) : d_ptr(new QScriptDeclarativeClassPrivate) @@ -132,6 +131,51 @@ QScriptDeclarativeClass::Object QScriptDeclarativeClass::object(const QScriptVal return static_cast(delegate)->object(); } +QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + + if (!d->isObject()) + return QScriptValue(); + + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSObject *object = d->jscValue.getObject(); + JSC::PropertySlot slot(const_cast(object)); + JSC::JSValue result; + + JSC::Identifier id(exec, (JSC::UString::Rep *)name); + + if (const_cast(object)->getOwnPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + if (QScript::isFunction(result)) + return d->engine->scriptValueFromJSCValue(result); + } + + return QScriptValue(); +} + +QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Identifier &name) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + + if (!d->isObject()) + return QScriptValue(); + + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSObject *object = d->jscValue.getObject(); + JSC::PropertySlot slot(const_cast(object)); + JSC::JSValue result; + + JSC::Identifier id(exec, (JSC::UString::Rep *)name); + + if (const_cast(object)->getOwnPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + return d->engine->scriptValueFromJSCValue(result); + } + + return QScriptValue(); +} + QScriptDeclarativeClass::~QScriptDeclarativeClass() { } @@ -141,34 +185,31 @@ QScriptEngine *QScriptDeclarativeClass::engine() const return d_ptr->engine; } -/* -QScriptDeclarativeClass::PersistentIdentifier * +QScriptDeclarativeClass::PersistentIdentifier QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) { QScriptEnginePrivate *p = static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifierPrivate *rv = new PersistentIdentifierPrivate; - rv->identifierValue = JSC::Identifier(exec, (UChar *)str.constData(), str.size()); - rv->identifier = (void *)rv->identifierValue.ustring().rep(); + PersistentIdentifier rv(true); + new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); + rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; } -QScriptDeclarativeClass::PersistentIdentifier * +QScriptDeclarativeClass::PersistentIdentifier QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id) { QScriptEnginePrivate *p = static_cast(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifierPrivate *rv = new PersistentIdentifierPrivate; - rv->identifierValue = JSC::Identifier(exec, (JSC::UString::Rep *)id); - rv->identifier = (void *)rv->identifierValue.ustring().rep(); + PersistentIdentifier rv(true); + new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id); + rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; } -*/ - QString QScriptDeclarativeClass::toString(const Identifier &identifier) { diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index a00a286..16f6942 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -71,15 +71,22 @@ public: static QScriptDeclarativeClass *scriptClass(const QScriptValue &); static Object object(const QScriptValue &); - template - class PersistentIdentifier : public T { + static QScriptValue function(const QScriptValue &, const Identifier &); + static QScriptValue property(const QScriptValue &, const Identifier &); + + class Q_SCRIPT_EXPORT PersistentIdentifier + { public: Identifier identifier; - ~PersistentIdentifier() { QScriptDeclarativeClass::destroyPersistentIdentifier(&d); } + PersistentIdentifier(); + ~PersistentIdentifier(); + PersistentIdentifier(const PersistentIdentifier &other); + PersistentIdentifier &operator=(const PersistentIdentifier &other); + private: friend class QScriptDeclarativeClass; - PersistentIdentifier() : identifier(0), d(0) {} + PersistentIdentifier(bool) : identifier(0), d(0) {} void *d; }; @@ -88,18 +95,8 @@ public: QScriptEngine *engine() const; - template - PersistentIdentifier *createPersistentIdentifier(const QString &str) { - PersistentIdentifier *rv = new PersistentIdentifier; - initPersistentIdentifier(&rv->d, &rv->identifier, str); - return rv; - } - template - PersistentIdentifier *createPersistentIdentifier(const Identifier &id) { - PersistentIdentifier *rv = new PersistentIdentifier; - initPersistentIdentifier(&rv->d, &rv->identifier, id); - return rv; - } + PersistentIdentifier createPersistentIdentifier(const QString &); + PersistentIdentifier createPersistentIdentifier(const Identifier &); QString toString(const Identifier &); @@ -116,10 +113,6 @@ public: virtual QVariant toVariant(const Object &, bool *ok = 0); virtual void destroyed(const Object &); - static void destroyPersistentIdentifier(void **); - void initPersistentIdentifier(void **, Identifier *, const QString &); - void initPersistentIdentifier(void **, Identifier *, const Identifier &); - protected: QScopedPointer d_ptr; }; -- cgit v0.12 From 3490b478ed02859f0355438efba900cd853e9c13 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 17:09:09 +1000 Subject: Reenable types/enums and move scripts into an isolated scope --- demos/declarative/samegame/content/samegame.js | 5 + demos/declarative/samegame/samegame.qml | 4 +- src/declarative/qml/qml.pri | 10 +- src/declarative/qml/qmlcompileddata.cpp | 4 + src/declarative/qml/qmlcompiler.cpp | 1 + src/declarative/qml/qmlcompiler_p.h | 2 + src/declarative/qml/qmlcomponent.cpp | 3 +- src/declarative/qml/qmlcontext.cpp | 5 +- src/declarative/qml/qmlcontext_p.h | 6 +- src/declarative/qml/qmlcontextscriptclass.cpp | 43 ++- src/declarative/qml/qmlcontextscriptclass_p.h | 3 + src/declarative/qml/qmlengine.cpp | 377 +++++++----------------- src/declarative/qml/qmlengine_p.h | 75 +---- src/declarative/qml/qmlintegercache.cpp | 4 +- src/declarative/qml/qmlintegercache_p.h | 9 +- src/declarative/qml/qmlobjectscriptclass.cpp | 22 +- src/declarative/qml/qmlobjectscriptclass_p.h | 6 +- src/declarative/qml/qmlpropertycache.cpp | 12 +- src/declarative/qml/qmlpropertycache_p.h | 10 +- src/declarative/qml/qmltypenamecache.cpp | 93 ++++++ src/declarative/qml/qmltypenamecache_p.h | 113 +++++++ src/declarative/qml/qmltypenamescriptclass.cpp | 159 ++++++++++ src/declarative/qml/qmltypenamescriptclass_p.h | 90 ++++++ src/declarative/qml/qmlvaluetypescriptclass.cpp | 150 ++++++++++ src/declarative/qml/qmlvaluetypescriptclass_p.h | 89 ++++++ src/declarative/util/qmlscript.cpp | 10 +- 26 files changed, 922 insertions(+), 383 deletions(-) create mode 100644 src/declarative/qml/qmltypenamecache.cpp create mode 100644 src/declarative/qml/qmltypenamecache_p.h create mode 100644 src/declarative/qml/qmltypenamescriptclass.cpp create mode 100644 src/declarative/qml/qmltypenamescriptclass_p.h create mode 100644 src/declarative/qml/qmlvaluetypescriptclass.cpp create mode 100644 src/declarative/qml/qmlvaluetypescriptclass_p.h diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js index 09057eb..7deafde 100755 --- a/demos/declarative/samegame/content/samegame.js +++ b/demos/declarative/samegame/content/samegame.js @@ -22,6 +22,11 @@ function timeStr(msecs) { return ret; } +function getTileSize() +{ + return tileSize; +} + function initBoard() { for(var i = 0; irelease(); + if (importCache) + importCache->release(); + qDeleteAll(programs); } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 5cb2158..4b5c5bf 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -644,6 +644,7 @@ void QmlCompiler::compileTree(Object *tree) output->bytecode << def; output->imports = unit->imports; + output->importCache = output->imports.cache(engine); Q_ASSERT(tree->metatype); static_cast(output->root) = *tree->metaObject(); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1cb66c7..fd361fd 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -64,6 +64,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -81,6 +82,7 @@ public: QByteArray name; QUrl url; QmlEnginePrivate::Imports imports; + QmlTypeNameCache *importCache; struct TypeReference { diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index fedc2da..5b1cbeb 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -517,7 +517,8 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings) static_cast(QObjectPrivate::get(context)); QmlContext *ctxt = new QmlContext(context, 0, true); static_cast(ctxt->d_func())->url = cc->url; - static_cast(ctxt->d_func())->imports = cc->imports; + static_cast(ctxt->d_func())->imports = cc->importCache; + cc->importCache->addref(); QmlVME vme; QObject *rv = vme.run(ctxt, cc, start, count, bindings); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 5e74d1a..968597c 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() : parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1), - highPriorityCount(0), expressions(0), idValues(0), idValueCount(0) + highPriorityCount(0), imports(0), expressions(0), idValues(0), idValueCount(0) { } @@ -307,6 +307,9 @@ QmlContext::~QmlContext() if (d->propertyNames) d->propertyNames->release(); + + if (d->imports) + d->imports->release(); } void QmlContextPrivate::invalidateEngines() diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 64faa6d..8fd2e92 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -62,6 +62,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -93,8 +94,11 @@ public: QScriptValueList scopeChain; + QList scripts; + QUrl url; - QmlEnginePrivate::Imports imports; + + QmlTypeNameCache *imports; void init(); diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index baea60a..d8ae4f0 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -42,6 +42,7 @@ #include "qmlcontextscriptclass_p.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -56,7 +57,7 @@ struct ContextData { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastPropertyIndex(-1), lastDefaultObject(-1) + lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -76,21 +77,32 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + + lastPropertyIndex = -1; + lastDefaultObject = -1; + lastData = 0; + QmlContext *bindContext = ((ContextData *)object)->context.data(); if (!bindContext) return 0; QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - - lastPropertyIndex = -1; - lastDefaultObject = -1; lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1; if (lastPropertyIndex != -1) return QScriptClass::HandlesReadAccess; // ### Check for attached properties + if (ep->currentExpression && cp->imports && bindContext == ep->currentExpression->context()) { + QmlTypeNameCache::Data *data = cp->imports->data(name); + + if (data) { + lastData = data; + return QScriptClass::HandlesReadAccess; + } + } + #if 0 QmlType *type = 0; ImportedNamespace *ns = 0; if (currentExpression && bindContext == currentExpression->context() && @@ -117,6 +129,11 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) + return QScriptClass::HandlesReadAccess; + } return 0; } @@ -145,7 +162,14 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif } #endif - if (lastPropertyIndex != -1) { + if (lastData) { + + if (lastData->type) + return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); + else + return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace); + + } else if (lastPropertyIndex != -1) { QScriptValue rv; if (lastPropertyIndex < cp->idValueCount) { @@ -161,15 +185,18 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif } ep->capturedProperties << - QmlEnginePrivate::CapturedProperty(bindContext, -1, - lastPropertyIndex + cp->notifyIndex); + QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex); return rv; - } else { + } else if(lastDefaultObject != -1) { // Default object property return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name); + } else { + + return lastFunction; + } } diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 9ef090d..a00e567 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -55,6 +55,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -77,8 +78,10 @@ protected: private: QmlEngine *engine; + QmlTypeNameCache::Data *lastData; int lastPropertyIndex; int lastDefaultObject; + QScriptValue lastFunction; uint m_id; }; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 4afd245..e67e42f 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -85,6 +85,7 @@ #include #include #include +#include #ifdef Q_OS_WIN // for %APPDATA% #include "qt_windows.h" @@ -274,114 +275,6 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) { } -struct QmlTypeNameBridge -{ - QObject *object; - QmlType *type; - QmlEnginePrivate::ImportedNamespace *ns; -}; -Q_DECLARE_METATYPE(QmlTypeNameBridge); - -struct QmlValueTypeReference { - QmlValueType *type; - QGuard object; - int property; -}; -Q_DECLARE_METATYPE(QmlValueTypeReference); - -void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id) -{ - Q_ASSERT(id == resolveData.safetyCheckId); - Q_Q(QmlEngine); - - resolveData.property.write(QmlScriptClass::toVariant(q, value)); -} - -QScriptClass::QueryFlags -QmlEnginePrivate::queryObject(const QString &propName, - uint *id, QObject *obj) -{ - resolveData.safetyCheckId++; - *id = resolveData.safetyCheckId; - resolveData.clear(); - - QScriptClass::QueryFlags rv = 0; - - QmlContext *ctxt = QmlEngine::contextForObject(obj); - if (!ctxt) - ctxt = rootContext; - QmlMetaProperty prop(obj, propName, ctxt); - - if (prop.type() == QmlMetaProperty::Invalid) { - QPair key = - qMakePair(obj->metaObject(), propName); - bool isFunction = false; - if (functionCache.contains(key)) { - isFunction = functionCache.value(key); - } else { - QScriptValue sobj = scriptEngine.newQObject(obj); - QScriptValue func = sobj.property(propName); - isFunction = func.isFunction(); - functionCache.insert(key, isFunction); - } - - if (isFunction) { - resolveData.object = obj; - resolveData.isFunction = true; - rv |= QScriptClass::HandlesReadAccess; - } - } else { - resolveData.object = obj; - resolveData.property = prop; - - rv |= QScriptClass::HandlesReadAccess; - if (prop.isWritable()) - rv |= QScriptClass::HandlesWriteAccess; - } - - return rv; -} - -QScriptValue QmlEnginePrivate::propertyObject(const QString &propName, - QObject *obj, uint id) -{ - Q_ASSERT(id == resolveData.safetyCheckId); - Q_ASSERT(resolveData.object); - - if (resolveData.isFunction) { - // ### Optimize - QScriptValue sobj = scriptEngine.newQObject(obj); - QScriptValue func = sobj.property(propName); - return func; - } else { - const QmlMetaProperty &prop = resolveData.property; - - if (prop.needsChangedNotifier()) - capturedProperties << CapturedProperty(prop); - - int propType = prop.propertyType(); - if (propType < QVariant::UserType && valueTypes[propType]) { - QmlValueTypeReference ref; - ref.type = valueTypes[propType]; - ref.object = obj; - ref.property = prop.coreIndex(); - return scriptEngine.newObject(valueTypeClass, scriptEngine.newVariant(QVariant::fromValue(ref))); - } - - QVariant var = prop.read(); - QObject *varobj = (propType < QVariant::UserType)?0:QmlMetaType::toQObject(var); - if (!varobj) - varobj = qvariant_cast(var); - if (varobj) { - return objectClass->newQObject(varobj); - } else { - return qScriptValueFromValue(&scriptEngine, var); - } - } - - return QScriptValue(); -} - /*! \class QmlEngine \brief The QmlEngine class provides an environment for instantiating QML components. @@ -1039,6 +932,35 @@ QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); } + +QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val) +{ + if (QmlMetaType::isObject(val.userType())) { + QObject *rv = *(QObject **)val.constData(); + return objectClass->newQObject(rv); + } else { + return qScriptValueFromValue(&scriptEngine, val); + } +} + +QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val) +{ + QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); + if (dc == objectClass) + return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == contextClass) + return QVariant(); + + QScriptClass *sc = val.scriptClass(); + if (!sc) { + return val.toVariant(); + } else if (sc == valueTypeClass) { + return valueTypeClass->toVariant(val); + } else { + return QVariant(); + } +} + QmlScriptClass::QmlScriptClass(QmlEngine *bindengine) : QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)), engine(bindengine) @@ -1060,175 +982,13 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) if (!sc) { return val.toVariant(); } else if (sc == ep->valueTypeClass) { - QmlValueTypeReference ref = - qvariant_cast(val.data().toVariant()); - - if (!ref.object) - return QVariant(); - - QMetaProperty p = ref.object->metaObject()->property(ref.property); - return p.read(ref.object); + return ep->valueTypeClass->toVariant(val); } return QVariant(); } ///////////////////////////////////////////////////////////// -QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine) -: QmlScriptClass(engine), object(0), type(0) -{ -} - -QmlTypeNameScriptClass::~QmlTypeNameScriptClass() -{ -} - -QmlTypeNameScriptClass::QueryFlags -QmlTypeNameScriptClass::queryProperty(const QScriptValue &scriptObject, - const QScriptString &name, - QueryFlags flags, uint *id) -{ - Q_UNUSED(flags); - - QmlTypeNameBridge bridge = - qvariant_cast(scriptObject.data().toVariant()); - - object = 0; - type = 0; - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - - if (bridge.ns) { - QmlType *type = 0; - ep->resolveTypeInNamespace(bridge.ns, name.toString().toUtf8(), - &type, 0, 0, 0); - if (type) { - object = bridge.object; - this->type = type; - return HandlesReadAccess; - } else { - return 0; - } - - } else { - Q_ASSERT(bridge.type); - QString strName = name.toString(); - if (strName.at(0).isUpper()) { - // Must be an enum - // ### Optimize - const char *enumName = strName.toUtf8().constData(); - const QMetaObject *metaObject = bridge.type->baseMetaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName); - if (value != -1) { - enumValue = value; - return HandlesReadAccess; - } - } - return 0; - } else { - // Must be an attached property - this->object = qmlAttachedPropertiesObjectById(bridge.type->index(), bridge.object); - if (!this->object) - return 0; - return ep->queryObject(strName, id, this->object); - } - } -} - -QScriptValue QmlTypeNameScriptClass::property(const QScriptValue &, - const QScriptString &propName, - uint id) -{ - QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - if (type) { - QmlTypeNameBridge tnb = { object, type, 0 }; - return ep->scriptEngine.newObject(ep->typeNameClass, ep->scriptEngine.newVariant(qVariantFromValue(tnb))); - } else if (object) { - return ep->propertyObject(propName, object, id); - } else { - return QScriptValue(enumValue); - } -} - -///////////////////////////////////////////////////////////// -QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) -: QmlScriptClass(bindEngine) -{ -} - -QmlValueTypeScriptClass::~QmlValueTypeScriptClass() -{ -} - -QmlValueTypeScriptClass::QueryFlags -QmlValueTypeScriptClass::queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id) -{ - Q_UNUSED(flags); - QmlValueTypeReference ref = - qvariant_cast(object.data().toVariant()); - - if (!ref.object) - return 0; - - QByteArray propName = name.toString().toUtf8(); - - int idx = ref.type->metaObject()->indexOfProperty(propName.constData()); - if (idx == -1) - return 0; - *id = idx; - - QMetaProperty prop = ref.object->metaObject()->property(idx); - - QmlValueTypeScriptClass::QueryFlags rv = - QmlValueTypeScriptClass::HandlesReadAccess; - if (prop.isWritable()) - rv |= QmlValueTypeScriptClass::HandlesWriteAccess; - - return rv; -} - -QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, - const QScriptString &name, - uint id) -{ - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast(object.data().toVariant()); - - if (!ref.object) - return QScriptValue(); - - ref.type->read(ref.object, ref.property); - - QMetaProperty p = ref.type->metaObject()->property(id); - QVariant rv = p.read(ref.type); - - return static_cast(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv); -} - -void QmlValueTypeScriptClass::setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value) -{ - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast(object.data().toVariant()); - - if (!ref.object) - return; - - QVariant v = QmlScriptClass::toVariant(engine, value); - - ref.type->read(ref.object, ref.property); - QMetaProperty p = ref.type->metaObject()->property(id); - p.write(ref.type, v); - ref.type->write(ref.object, ref.property); -} - struct QmlEnginePrivate::ImportedNamespace { QStringList urls; QList majversions; @@ -1395,6 +1155,7 @@ public: int ref; private: + friend class QmlEnginePrivate::Imports; QmlEnginePrivate::ImportedNamespace unqualifiedset; QHash set; }; @@ -1425,6 +1186,80 @@ QmlEnginePrivate::Imports::~Imports() delete d; } +#include +#include +static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePrivate::ImportedNamespace &set, QmlTypeNameCache *cache) +{ + if (!cache) + cache = new QmlTypeNameCache(engine); + + QList types = QmlMetaType::qmlTypes(); + + for (int ii = 0; ii < set.urls.count(); ++ii) { + if (!set.isBuiltin.at(ii)) + continue; + + QByteArray base = set.urls.at(ii).toUtf8() + "/"; + int major = set.majversions.at(ii); + int minor = set.minversions.at(ii); + + foreach (QmlType *type, types) { + if (type->qmlTypeName().startsWith(base) && + type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && + type->majorVersion() == major && type->minMinorVersion() <= minor && + type->maxMinorVersion() >= minor) { + + QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length())); + + cache->add(name, type); + } + } + } + + return cache; +} + +QmlTypeNameCache *QmlEnginePrivate::Imports::cache(QmlEngine *engine) const +{ + const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset; + + QmlTypeNameCache *cache = new QmlTypeNameCache(engine); + + for (QHash::ConstIterator iter = d->set.begin(); + iter != d->set.end(); ++iter) { + + QmlTypeNameCache::Data *d = cache->data(iter.key()); + if (d) { + if (!d->typeNamespace) + cacheForNamespace(engine, *(*iter), d->typeNamespace); + } else { + QmlTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0); + cache->add(iter.key(), nc); + nc->release(); + } + } + + cacheForNamespace(engine, set, cache); + + return cache; +} + +/* +QStringList QmlEnginePrivate::Imports::unqualifiedSet() const +{ + QStringList rv; + + const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset; + + for (int ii = 0; ii < set.urls.count(); ++ii) { + if (set.isBuiltin.at(ii)) + rv << set.urls.at(ii); + } + + return rv; +} +*/ + /*! Sets the base URL to be used for all relative file imports added. */ diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 231388d..7978023 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -75,6 +75,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -92,6 +93,8 @@ class QNetworkReply; class QNetworkAccessManager; class QmlAbstractBinding; class QScriptDeclarativeClass; +class QmlTypeNameScriptClass; +class QmlTypeNameCache; class QmlEnginePrivate : public QObjectPrivate { @@ -102,13 +105,6 @@ public: void init(); - QScriptClass::QueryFlags queryObject(const QString &name, uint *id, - QObject *); - QScriptValue propertyObject(const QString &propName, QObject *, - uint id = 0); - void setPropertyObject(const QScriptValue &, uint id); - - struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) : object(o), coreIndex(c), notifyIndex(n) {} @@ -128,25 +124,6 @@ public: #endif struct ImportedNamespace; - struct ResolveData { - ResolveData() : safetyCheckId(0) {} - int safetyCheckId; - - void clear() { - object = 0; context = 0; - type = 0; ns = 0; - contextIndex = -1; isFunction = false; - } - QObject *object; - QmlContext *context; - - QmlType *type; - QmlEnginePrivate::ImportedNamespace *ns; - - int contextIndex; - bool isFunction; - QmlMetaProperty property; - } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; @@ -211,9 +188,6 @@ public: } QmlValueTypeFactory valueTypes; - // ### Fixme - typedef QHash, bool> FunctionCache; - FunctionCache functionCache; QHash propertyCache; QmlPropertyCache *cache(QObject *obj) { @@ -228,6 +202,7 @@ public: return rv; } + // ### This whole class is embarrassing struct Imports { Imports(); ~Imports(); @@ -237,6 +212,8 @@ public: void setBaseUrl(const QUrl& url); QUrl baseUrl() const; + QmlTypeNameCache *cache(QmlEngine *) const; + private: friend class QmlEnginePrivate; QmlImportsPrivate *d; @@ -261,6 +238,9 @@ public: QHash m_qmlLists; QHash m_compositeTypes; + QScriptValue scriptValueFromVariant(const QVariant &); + QVariant scriptValueToVariant(const QScriptValue &); + static QScriptValue qmlScriptObject(QObject*, QmlEngine*); static QScriptValue createComponent(QScriptContext*, QScriptEngine*); static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*); @@ -292,43 +272,6 @@ protected: QmlEngine *engine; }; -class QmlTypeNameScriptClass : public QmlScriptClass -{ -public: - QmlTypeNameScriptClass(QmlEngine *); - ~QmlTypeNameScriptClass(); - - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - -private: - QObject *object; - QmlType *type; - quint32 enumValue; -}; - -class QmlValueTypeScriptClass : public QmlScriptClass -{ -public: - QmlValueTypeScriptClass(QmlEngine *); - ~QmlValueTypeScriptClass(); - - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - virtual void setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value); -}; - QT_END_NAMESPACE #endif // QMLENGINE_P_H diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp index 1bc4086..564faaa 100644 --- a/src/declarative/qml/qmlintegercache.cpp +++ b/src/declarative/qml/qmlintegercache.cpp @@ -62,9 +62,7 @@ void QmlIntegerCache::add(const QString &id, int value) QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); // ### use contextClass - QScriptDeclarativeClass::PersistentIdentifier *d = - enginePriv->objectClass->createPersistentIdentifier(id); - d->value = value; + Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value); stringCache.insert(id, d); identifierCache.insert(d->identifier, d); diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h index fda80c6..e11e0be 100644 --- a/src/declarative/qml/qmlintegercache_p.h +++ b/src/declarative/qml/qmlintegercache_p.h @@ -74,12 +74,15 @@ public: static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *); private: - struct Data { + struct Data : public QScriptDeclarativeClass::PersistentIdentifier { + Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v) + : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {} + int value; }; - typedef QHash *> StringCache; - typedef QHash *> IdentifierCache; + typedef QHash StringCache; + typedef QHash IdentifierCache; StringCache stringCache; IdentifierCache identifierCache; diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index bb5f191..6a34a2f 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -64,14 +64,13 @@ QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); m_destroy = scriptEngine->newFunction(destroy); - m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); + m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); m_toString = scriptEngine->newFunction(tostring); - m_toStringId = createPersistentIdentifier(QLatin1String("toString")); + m_toStringId = createPersistentIdentifier(QLatin1String("toString")); } QmlObjectScriptClass::~QmlObjectScriptClass() { - delete m_destroyId; } QScriptValue QmlObjectScriptClass::newQObject(QObject *object) @@ -100,8 +99,8 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, Q_UNUSED(flags); lastData = 0; - if (name == m_destroyId->identifier || - name == m_toStringId->identifier) + if (name == m_destroyId.identifier || + name == m_toStringId.identifier) return QScriptClass::HandlesReadAccess; if (!obj) @@ -140,9 +139,9 @@ QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifi QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name) { - if (name == m_destroyId->identifier) + if (name == m_destroyId.identifier) return m_destroy; - else if (name == m_toStringId->identifier) + else if (name == m_toStringId.identifier) return m_toString; Q_ASSERT(lastData); @@ -156,6 +155,11 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QScriptValue sobj = scriptEngine->newQObject(obj); return sobj.property(toString(name)); } else { + if (lastData->propType < QVariant::UserType) { + QmlValueType *valueType = enginePriv->valueTypes[lastData->propType]; + if (valueType) + return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); + } QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { @@ -167,7 +171,7 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QObject *rv = *(QObject **)var.constData(); return newQObject(rv); } else { - return qScriptValueFromValue(scriptEngine, var); + return enginePriv->scriptValueFromVariant(var); } } @@ -250,5 +254,5 @@ QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngin return engine->nullValue(); } - QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index cd67fac..c86abdb 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -86,13 +86,11 @@ protected: virtual void destroyed(const Object &); private: - uint m_id; QmlPropertyCache::Data *lastData; QmlPropertyCache::Data local; - struct Dummy {}; - PersistentIdentifier *m_destroyId; - PersistentIdentifier *m_toStringId; + PersistentIdentifier m_destroyId; + PersistentIdentifier m_toStringId; QScriptValue m_destroy; QScriptValue m_toString; diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index cc4c2ab..d7b087b 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -155,8 +155,8 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject QMetaProperty p = metaObject->property(ii); QString propName = QLatin1String(p.name()); - QScriptDeclarativeClass::PersistentIdentifier *data = - enginePriv->objectClass->createPersistentIdentifier(propName); + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); data->load(p); @@ -166,7 +166,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject continue; cache->stringCache.insert(propName, data); - cache->identifierCache.insert(data->identifier, data); + cache->identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } @@ -183,13 +183,13 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject if (cache->stringCache.contains(methodName)) continue; - QScriptDeclarativeClass::PersistentIdentifier *data = - enginePriv->objectClass->createPersistentIdentifier(methodName); + RData *data = new RData; + data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName); data->load(m); cache->stringCache.insert(methodName, data); - cache->identifierCache.insert(data->identifier, data); + cache->identifierCache.insert(data->identifier.identifier, data); data->addref(); data->addref(); } diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 82b8737..f1b1219 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -113,11 +113,13 @@ public: Data *property(int) const; private: - struct RData : public Data, public QmlRefCount {}; + struct RData : public Data, public QmlRefCount { + QScriptDeclarativeClass::PersistentIdentifier identifier; + }; - typedef QVector *> IndexCache; - typedef QHash *> StringCache; - typedef QHash *> IdentifierCache; + typedef QVector IndexCache; + typedef QHash StringCache; + typedef QHash IdentifierCache; IndexCache indexCache; StringCache stringCache; diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp new file mode 100644 index 0000000..2b0f2c9 --- /dev/null +++ b/src/declarative/qml/qmltypenamecache.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmltypenamecache_p.h" + +QT_BEGIN_NAMESPACE + +QmlTypeNameCache::QmlTypeNameCache(QmlEngine *e) +: engine(e) +{ +} + +QmlTypeNameCache::~QmlTypeNameCache() +{ + qDeleteAll(stringCache); +} + +void QmlTypeNameCache::add(const QString &name, QmlType *type) +{ + if (stringCache.contains(name)) + return; + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + RData *data = new RData; + // ### Use typename class + data->identifier = ep->objectClass->createPersistentIdentifier(name); + data->type = type; + stringCache.insert(name, data); + identifierCache.insert(data->identifier.identifier, data); +} + +void QmlTypeNameCache::add(const QString &name, QmlTypeNameCache *typeNamespace) +{ + if (stringCache.contains(name)) + return; + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + RData *data = new RData; + // ### Use typename class + data->identifier = ep->objectClass->createPersistentIdentifier(name); + data->typeNamespace = typeNamespace; + stringCache.insert(name, data); + identifierCache.insert(data->identifier.identifier, data); + typeNamespace->addref(); +} + +QmlTypeNameCache::Data *QmlTypeNameCache::data(const QString &id) const +{ + return stringCache.value(id); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h new file mode 100644 index 0000000..6022b43 --- /dev/null +++ b/src/declarative/qml/qmltypenamecache_p.h @@ -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$ +** +****************************************************************************/ + +#ifndef QMLTYPENAMECACHE_P_H +#define QMLTYPENAMECACHE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlType; +class QmlEngine; +class QmlTypeNameCache : public QmlRefCount +{ +public: + QmlTypeNameCache(QmlEngine *); + virtual ~QmlTypeNameCache(); + + struct Data { + inline Data(); + inline ~Data(); + QmlType *type; + QmlTypeNameCache *typeNamespace; + }; + + void add(const QString &, QmlType *); + void add(const QString &, QmlTypeNameCache *); + + Data *data(const QString &) const; + inline Data *data(const QScriptDeclarativeClass::Identifier &id) const; + +private: + struct RData : public Data { + QScriptDeclarativeClass::PersistentIdentifier identifier; + }; + typedef QHash StringCache; + typedef QHash IdentifierCache; + + StringCache stringCache; + IdentifierCache identifierCache; + QmlEngine *engine; +}; + +QmlTypeNameCache::Data::Data() +: type(0), typeNamespace(0) +{ +} + +QmlTypeNameCache::Data::~Data() +{ + if (typeNamespace) typeNamespace->release(); +} + +QmlTypeNameCache::Data *QmlTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const +{ + return identifierCache.value(id); +} + +QT_END_NAMESPACE + +#endif // QMLTYPENAMECACHE_P_H + diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp new file mode 100644 index 0000000..29e2978 --- /dev/null +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmltypenamescriptclass_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +struct TypeNameData { + TypeNameData(QObject *o, QmlType *t) : object(o), type(t), typeNamespace(0) {} + TypeNameData(QObject *o, QmlTypeNameCache *n) : object(o), type(0), typeNamespace(n) { + if (typeNamespace) typeNamespace->addref(); + } + ~TypeNameData() { + if (typeNamespace) typeNamespace->release(); + } + + QObject *object; + QmlType *type; + QmlTypeNameCache *typeNamespace; +}; + +QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), + engine(bindEngine), object(0), type(0) +{ +} + +QmlTypeNameScriptClass::~QmlTypeNameScriptClass() +{ +} + +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, type)); +} + +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, ns)); +} + + +QScriptClass::QueryFlags +QmlTypeNameScriptClass::queryProperty(const Object &obj, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + Q_UNUSED(flags); + + TypeNameData *data = (TypeNameData *)obj; + + object = 0; + type = 0; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + + if (data->typeNamespace) { + + QmlTypeNameCache::Data *d = data->typeNamespace->data(name); + if (d && d->type) { + type = d->type; + return QScriptClass::HandlesReadAccess; + } else { + return 0; + } + + } else { + Q_ASSERT(data->type); + + QString strName = toString(name); + + if (strName.at(0).isUpper()) { + // Must be an enum + // ### Optimize + const char *enumName = strName.toUtf8().constData(); + const QMetaObject *metaObject = data->type->baseMetaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName); + if (value != -1) { + enumValue = value; + return QScriptClass::HandlesReadAccess; + } + } + return 0; + } else { + // Must be an attached property + object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); + if (!object) return 0; + return ep->objectClass->queryProperty(object, name, flags); + } + } +} + +QScriptValue QmlTypeNameScriptClass::property(const Object &obj, const Identifier &name) +{ + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + if (type) { + return newObject(object, type); + } else if (object) { + return ep->objectClass->property(((TypeNameData *)obj)->object, name); + } else { + return QScriptValue(enumValue); + } +} + +void QmlTypeNameScriptClass::setProperty(const Object &o, const Identifier &n, const QScriptValue &v) +{ + Q_ASSERT(object); + Q_ASSERT(!type); + + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h new file mode 100644 index 0000000..c642ea4 --- /dev/null +++ b/src/declarative/qml/qmltypenamescriptclass_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLTYPENAMESCRIPTCLASS_P_H +#define QMLTYPENAMESCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlType; +class QmlTypeNameCache; +class QmlTypeNameScriptClass : public QScriptDeclarativeClass +{ +public: + QmlTypeNameScriptClass(QmlEngine *); + ~QmlTypeNameScriptClass(); + + QScriptValue newObject(QObject *, QmlType *); + QScriptValue newObject(QObject *, QmlTypeNameCache *); + +protected: + virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + QScriptClass::QueryFlags flags); + + virtual QScriptValue property(const Object &, const Identifier &); + virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + +private: + QmlEngine *engine; + QObject *object; + QmlType *type; + quint32 enumValue; +}; + +QT_END_NAMESPACE + +#endif // QMLTYPENAMESCRIPTCLASS_P_H + diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp new file mode 100644 index 0000000..da6c73d --- /dev/null +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlvaluetypescriptclass_p.h" +#include + +QT_BEGIN_NAMESPACE + +struct QmlValueTypeReference { + QmlValueType *type; + QGuard object; + int property; +}; +Q_DECLARE_METATYPE(QmlValueTypeReference); + +QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) +: QScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +{ +} + +QmlValueTypeScriptClass::~QmlValueTypeScriptClass() +{ +} + +QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type) +{ + QmlValueTypeReference ref = { type, object, coreIndex }; + return QScriptValue(); +} + +QmlValueTypeScriptClass::QueryFlags +QmlValueTypeScriptClass::queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id) +{ + Q_UNUSED(flags); + QmlValueTypeReference ref = + qvariant_cast(object.data().toVariant()); + + if (!ref.object) + return 0; + + QByteArray propName = name.toString().toUtf8(); + + int idx = ref.type->metaObject()->indexOfProperty(propName.constData()); + if (idx == -1) + return 0; + *id = idx; + + QMetaProperty prop = ref.object->metaObject()->property(idx); + + QmlValueTypeScriptClass::QueryFlags rv = + QmlValueTypeScriptClass::HandlesReadAccess; + if (prop.isWritable()) + rv |= QmlValueTypeScriptClass::HandlesWriteAccess; + + return rv; +} + +QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, + const QScriptString &name, + uint id) +{ + Q_UNUSED(name); + QmlValueTypeReference ref = + qvariant_cast(object.data().toVariant()); + + if (!ref.object) + return QScriptValue(); + + ref.type->read(ref.object, ref.property); + + QMetaProperty p = ref.type->metaObject()->property(id); + QVariant rv = p.read(ref.type); + + return static_cast(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv); +} + +void QmlValueTypeScriptClass::setProperty(QScriptValue &object, + const QScriptString &name, + uint id, + const QScriptValue &value) +{ + Q_UNUSED(name); + QmlValueTypeReference ref = + qvariant_cast(object.data().toVariant()); + + if (!ref.object) + return; + + QVariant v = QmlScriptClass::toVariant(engine, value); + + ref.type->read(ref.object, ref.property); + QMetaProperty p = ref.type->metaObject()->property(id); + p.write(ref.type, v); + ref.type->write(ref.object, ref.property); +} + +QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) +{ + QmlValueTypeReference ref = + qvariant_cast(val.data().toVariant()); + + if (!ref.object) + return QVariant(); + + QMetaProperty p = ref.object->metaObject()->property(ref.property); + return p.read(ref.object); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h new file mode 100644 index 0000000..d656a22 --- /dev/null +++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLVALUETYPESCRIPTCLASS_P_H +#define QMLVALUETYPESCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlValueType; +class QmlValueTypeScriptClass : public QScriptClass +{ +public: + QmlValueTypeScriptClass(QmlEngine *); + ~QmlValueTypeScriptClass(); + + QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *); + + virtual QueryFlags queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id); + virtual QScriptValue property(const QScriptValue &object, + const QScriptString &name, + uint id); + virtual void setProperty(QScriptValue &object, + const QScriptString &name, + uint id, + const QScriptValue &value); + + QVariant toVariant(const QScriptValue &); +private: + QmlEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QMLVALUETYPESCRIPTCLASS_P_H + diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp index de2128d..2031a54 100644 --- a/src/declarative/util/qmlscript.cpp +++ b/src/declarative/util/qmlscript.cpp @@ -179,10 +179,14 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushContext(); - for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) { + for (int i = context->d_func()->scopeChain.size() - 1; i >= 0; --i) { scriptContext->pushScope(context->d_func()->scopeChain.at(i)); } - scriptContext->setActivationObject(context->d_func()->scopeChain.at(0)); + + QScriptValue scope = scriptEngine->newObject(); + scriptContext->pushScope(scope); + + scriptContext->setActivationObject(scope); QScriptValue val = scriptEngine->evaluate(script, source); if (scriptEngine->hasUncaughtException()) { @@ -200,6 +204,8 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s } scriptEngine->popContext(); + + context->d_func()->scripts.append(scope); } QT_END_NAMESPACE -- cgit v0.12 From a712a6243be29dbfa49c3d1705c8b1babd8c7a1a Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 18:01:55 +1000 Subject: Tweak api to improve ownership issues --- src/script/bridge/qscriptdeclarativeclass.cpp | 23 +++++++++-------------- src/script/bridge/qscriptdeclarativeclass_p.h | 22 +++++++++++----------- src/script/bridge/qscriptdeclarativeobject.cpp | 7 ++----- src/script/bridge/qscriptdeclarativeobject_p.h | 6 +++--- 4 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 371a3c3..62c1afc 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -94,7 +94,7 @@ QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine, QScriptDeclarativeClass *scriptClass, - Object object) + Object *object) { Q_ASSERT(engine); Q_ASSERT(scriptClass); @@ -119,7 +119,7 @@ QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue return static_cast(delegate)->scriptClass(); } -QScriptDeclarativeClass::Object QScriptDeclarativeClass::object(const QScriptValue &v) +QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) @@ -218,7 +218,7 @@ QString QScriptDeclarativeClass::toString(const Identifier &identifier) } QScriptClass::QueryFlags -QScriptDeclarativeClass::queryProperty(const Object &object, const Identifier &name, +QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(object); @@ -227,14 +227,14 @@ QScriptDeclarativeClass::queryProperty(const Object &object, const Identifier &n return 0; } -QScriptValue QScriptDeclarativeClass::property(const Object &object, const Identifier &name) +QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); Q_UNUSED(name); return QScriptValue(); } -void QScriptDeclarativeClass::setProperty(const Object &object, const Identifier &name, +void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { Q_UNUSED(object); @@ -243,31 +243,26 @@ void QScriptDeclarativeClass::setProperty(const Object &object, const Identifier } QScriptValue::PropertyFlags -QScriptDeclarativeClass::propertyFlags(const Object &object, const Identifier &name) +QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name) { Q_UNUSED(object); Q_UNUSED(name); return 0; } -QStringList QScriptDeclarativeClass::propertyNames(const Object &object) +QStringList QScriptDeclarativeClass::propertyNames(Object *object) { Q_UNUSED(object); return QStringList(); } -void QScriptDeclarativeClass::destroyed(const Object &object) -{ - Q_UNUSED(object); -} - -QObject *QScriptDeclarativeClass::toQObject(const Object &, bool *ok) +QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok) { if (ok) *ok = false; return 0; } -QVariant QScriptDeclarativeClass::toVariant(const Object &, bool *ok) +QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok) { if (ok) *ok = false; return QVariant(); diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 16f6942..07cfad1 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -65,11 +65,12 @@ class Q_SCRIPT_EXPORT QScriptDeclarativeClass { public: typedef void* Identifier; - typedef void* Object; - static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object); + struct Object { virtual ~Object() {} }; + + static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *); static QScriptDeclarativeClass *scriptClass(const QScriptValue &); - static Object object(const QScriptValue &); + static Object *object(const QScriptValue &); static QScriptValue function(const QScriptValue &, const Identifier &); static QScriptValue property(const QScriptValue &, const Identifier &); @@ -100,18 +101,17 @@ public: QString toString(const Identifier &); - virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual QScriptValue property(const Object &, const Identifier &); - virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); - virtual QScriptValue::PropertyFlags propertyFlags(const Object &, const Identifier &); + virtual QScriptValue property(Object *, const Identifier &); + virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); + virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &); - virtual QStringList propertyNames(const Object &); + virtual QStringList propertyNames(Object *); - virtual QObject *toQObject(const Object &, bool *ok = 0); - virtual QVariant toVariant(const Object &, bool *ok = 0); - virtual void destroyed(const Object &); + virtual QObject *toQObject(Object *, bool *ok = 0); + virtual QVariant toVariant(Object *, bool *ok = 0); protected: QScopedPointer d_ptr; diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index 62c2686..aa811d1 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -64,14 +64,14 @@ namespace QScript { DeclarativeObjectDelegate::DeclarativeObjectDelegate(QScriptDeclarativeClass *c, - QScriptDeclarativeClass::Object &o) + QScriptDeclarativeClass::Object *o) : m_class(c), m_object(o) { } DeclarativeObjectDelegate::~DeclarativeObjectDelegate() { - m_class->destroyed(m_object); + delete m_object; } QScriptObjectDelegate::Type DeclarativeObjectDelegate::type() const @@ -126,7 +126,6 @@ bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* objec const JSC::Identifier &propertyName, unsigned &attribs) const { - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); QScriptClass::QueryFlags flags = @@ -154,8 +153,6 @@ void DeclarativeObjectDelegate::getPropertyNames(QScriptObject* object, JSC::Exe JSC::PropertyNameArray &propertyNames, unsigned listedAttributes) { - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); - QStringList properties = m_class->propertyNames(m_object); for (int ii = 0; ii < properties.count(); ++ii) { const QString &name = properties.at(ii); diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h index 87375d8..ccb07bc 100644 --- a/src/script/bridge/qscriptdeclarativeobject_p.h +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -68,13 +68,13 @@ namespace QScript class DeclarativeObjectDelegate : public QScriptObjectDelegate { public: - DeclarativeObjectDelegate(QScriptDeclarativeClass *c, QScriptDeclarativeClass::Object &o); + DeclarativeObjectDelegate(QScriptDeclarativeClass *c, QScriptDeclarativeClass::Object *o); ~DeclarativeObjectDelegate(); virtual Type type() const; QScriptDeclarativeClass *scriptClass() const { return m_class; } - QScriptDeclarativeClass::Object object() const { return m_object; } + QScriptDeclarativeClass::Object *object() const { return m_object; } virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, const JSC::Identifier& propertyName, @@ -100,7 +100,7 @@ public: private: QScriptDeclarativeClass *m_class; - QScriptDeclarativeClass::Object m_object; + QScriptDeclarativeClass::Object *m_object; }; } // namespace QScript -- cgit v0.12 From 5b37c01aa721057ad0cbef16a79cf179e3c53934 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 18:02:14 +1000 Subject: Update to new QScriptDeclarativeClass API --- src/declarative/qml/qmlcontextscriptclass.cpp | 48 ++++---------------------- src/declarative/qml/qmlcontextscriptclass_p.h | 6 ++-- src/declarative/qml/qmlobjectscriptclass.cpp | 23 +++++------- src/declarative/qml/qmlobjectscriptclass_p.h | 9 +++-- src/declarative/qml/qmltypenamecache.cpp | 1 + src/declarative/qml/qmltypenamecache_p.h | 1 - src/declarative/qml/qmltypenamescriptclass.cpp | 12 +++---- src/declarative/qml/qmltypenamescriptclass_p.h | 6 ++-- 8 files changed, 31 insertions(+), 75 deletions(-) diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index d8ae4f0..4b149f7 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE -struct ContextData { +struct ContextData : public QScriptDeclarativeClass::Object { ContextData(QmlContext *c) : context(c) {} QGuard context; }; @@ -69,11 +69,11 @@ QScriptValue QmlContextScriptClass::newContext(QmlContext *context) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, (Object)new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context)); } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(const Object &object, const Identifier &name, +QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); @@ -93,7 +93,6 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam if (lastPropertyIndex != -1) return QScriptClass::HandlesReadAccess; - // ### Check for attached properties if (ep->currentExpression && cp->imports && bindContext == ep->currentExpression->context()) { QmlTypeNameCache::Data *data = cp->imports->data(name); @@ -103,22 +102,6 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam } } -#if 0 - QmlType *type = 0; ImportedNamespace *ns = 0; - if (currentExpression && bindContext == currentExpression->context() && - propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) { - - if (type || ns) { - // Must be either an attached property, or an enum - resolveData.object = bindContext->d_func()->defaultObjects.first(); - resolveData.type = type; - resolveData.ns = ns; - return QScriptClass::HandlesReadAccess; - } - - } -#endif - for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags); @@ -137,12 +120,10 @@ QmlContextScriptClass::queryProperty(const Object &object, const Identifier &nam return 0; } -QScriptValue QmlContextScriptClass::property(const Object &object, const Identifier &name) +QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); - Q_ASSERT(lastPropertyIndex != -1 || lastDefaultObject != -1); - QmlContext *bindContext = ((ContextData *)object)->context.data(); Q_ASSERT(bindContext); @@ -150,18 +131,6 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - // ### Check for attached properties -#if 0 - if (resolveData.type || resolveData.ns) { - QmlTypeNameBridge tnb = { - resolveData.object, - resolveData.type, - resolveData.ns - }; - return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb))); - } -#endif - if (lastData) { if (lastData->type) @@ -176,12 +145,7 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data()); } else { QVariant value = cp->propertyValues.at(lastPropertyIndex); - if (QmlMetaType::isObject(value.userType())) { - rv = ep->objectClass->newQObject(QmlMetaType::toQObject(value)); - } else { - // ### Shouldn't this be qScriptValueFromValue() - rv = ep->scriptEngine.newVariant(value); - } + return ep->scriptValueFromVariant(value); } ep->capturedProperties << @@ -200,7 +164,7 @@ QScriptValue QmlContextScriptClass::property(const Object &object, const Identif } } -void QmlContextScriptClass::setProperty(const Object &object, const Identifier &name, +void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { Q_ASSERT(lastDefaultObject != -1); diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index a00e567..acb8926 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -70,10 +70,10 @@ public: QScriptValue newContext(QmlContext *); protected: - virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual QScriptValue property(const Object &, const Identifier &); - virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + virtual QScriptValue property(Object *, const Identifier &); + virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: QmlEngine *engine; diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 6a34a2f..33fd409 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE -struct ObjectData { +struct ObjectData : public QScriptDeclarativeClass::Object { ObjectData(QObject *o) : object(o) {} QGuard object; }; @@ -77,7 +77,7 @@ QScriptValue QmlObjectScriptClass::newQObject(QObject *object) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, (Object)new ObjectData(object)); + return newObject(scriptEngine, this, new ObjectData(object)); } QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const @@ -86,7 +86,7 @@ QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const } QScriptClass::QueryFlags -QmlObjectScriptClass::queryProperty(const Object &object, const Identifier &name, +QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { return queryProperty(toQObject(object), name, flags); @@ -132,7 +132,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return rv; } -QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifier &name) +QScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name) { return property(toQObject(object), name); } @@ -155,7 +155,7 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QScriptValue sobj = scriptEngine->newQObject(obj); return sobj.property(toString(name)); } else { - if (lastData->propType < QVariant::UserType) { + if ((uint)lastData->propType < QVariant::UserType) { QmlValueType *valueType = enginePriv->valueTypes[lastData->propType]; if (valueType) return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); @@ -177,7 +177,7 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name } } -void QmlObjectScriptClass::setProperty(const Object &object, +void QmlObjectScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { @@ -193,7 +193,6 @@ void QmlObjectScriptClass::setProperty(QObject *obj, Q_ASSERT(obj); Q_ASSERT(lastData); - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); // ### Can well known types be optimized? @@ -201,7 +200,7 @@ void QmlObjectScriptClass::setProperty(QObject *obj, QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context()); } -QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok) +QObject *QmlObjectScriptClass::toQObject(Object *object, bool *ok) { if (ok) *ok = true; @@ -209,13 +208,7 @@ QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok) return data->object.data(); } -void QmlObjectScriptClass::destroyed(const Object &object) -{ - ObjectData *data = (ObjectData*)object; - delete data; -} - -QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *engine) +QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *) { QObject* obj = context->thisObject().toQObject(); diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index c86abdb..6406f0d 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -77,13 +77,12 @@ public: void setProperty(QObject *, const Identifier &name, const QScriptValue &); protected: - virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual QScriptValue property(const Object &, const Identifier &); - virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); - virtual QObject *toQObject(const Object &, bool *ok = 0); - virtual void destroyed(const Object &); + virtual QScriptValue property(Object *, const Identifier &); + virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); + virtual QObject *toQObject(Object *, bool *ok = 0); private: QmlPropertyCache::Data *lastData; diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp index 2b0f2c9..aa1c938 100644 --- a/src/declarative/qml/qmltypenamecache.cpp +++ b/src/declarative/qml/qmltypenamecache.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qmltypenamecache_p.h" +#include QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h index 6022b43..f11fe68 100644 --- a/src/declarative/qml/qmltypenamecache_p.h +++ b/src/declarative/qml/qmltypenamecache_p.h @@ -55,7 +55,6 @@ #include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index 29e2978..7c5e5b0 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -struct TypeNameData { +struct TypeNameData : public QScriptDeclarativeClass::Object { TypeNameData(QObject *o, QmlType *t) : object(o), type(t), typeNamespace(0) {} TypeNameData(QObject *o, QmlTypeNameCache *n) : object(o), type(0), typeNamespace(n) { if (typeNamespace) typeNamespace->addref(); @@ -73,19 +73,19 @@ QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, type)); + return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type)); } QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return QScriptDeclarativeClass::newObject(scriptEngine, this, (Object)new TypeNameData(object, ns)); + return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns)); } QScriptClass::QueryFlags -QmlTypeNameScriptClass::queryProperty(const Object &obj, const Identifier &name, +QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); @@ -134,7 +134,7 @@ QmlTypeNameScriptClass::queryProperty(const Object &obj, const Identifier &name, } } -QScriptValue QmlTypeNameScriptClass::property(const Object &obj, const Identifier &name) +QScriptValue QmlTypeNameScriptClass::property(Object *obj, const Identifier &name) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); if (type) { @@ -146,7 +146,7 @@ QScriptValue QmlTypeNameScriptClass::property(const Object &obj, const Identifie } } -void QmlTypeNameScriptClass::setProperty(const Object &o, const Identifier &n, const QScriptValue &v) +void QmlTypeNameScriptClass::setProperty(Object *o, const Identifier &n, const QScriptValue &v) { Q_ASSERT(object); Q_ASSERT(!type); diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h index c642ea4..3bd51e6 100644 --- a/src/declarative/qml/qmltypenamescriptclass_p.h +++ b/src/declarative/qml/qmltypenamescriptclass_p.h @@ -71,11 +71,11 @@ public: QScriptValue newObject(QObject *, QmlTypeNameCache *); protected: - virtual QScriptClass::QueryFlags queryProperty(const Object &, const Identifier &, + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual QScriptValue property(const Object &, const Identifier &); - virtual void setProperty(const Object &, const Identifier &name, const QScriptValue &); + virtual QScriptValue property(Object *, const Identifier &); + virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: QmlEngine *engine; -- cgit v0.12 From 44638d0f310aad59336ad44f427351a4b9c40f15 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 18:28:37 +1000 Subject: Implement QmlValueTypeScriptClass::newObject() --- src/declarative/qml/qmlvaluetypescriptclass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index da6c73d..503d64f 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -63,7 +63,8 @@ QmlValueTypeScriptClass::~QmlValueTypeScriptClass() QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type) { QmlValueTypeReference ref = { type, object, coreIndex }; - return QScriptValue(); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + return scriptEngine->newObject(this, scriptEngine->newVariant(qVariantFromValue(ref))); } QmlValueTypeScriptClass::QueryFlags -- cgit v0.12 From a6a2a2373c63ec3c67be62814bc3391de1338883 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 18:33:28 +1000 Subject: Crash --- src/declarative/qml/qmltypenamescriptclass.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index 7c5e5b0..61b57c4 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -125,13 +125,15 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, } } return 0; - } else { + } else if (data->object) { // Must be an attached property object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); if (!object) return 0; return ep->objectClass->queryProperty(object, name, flags); } } + + return 0; } QScriptValue QmlTypeNameScriptClass::property(Object *obj, const Identifier &name) -- cgit v0.12 From b4001abf71b3335cedfaf72ca3b7f25ea46be35c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 18:37:42 +1000 Subject: Add attached property ECMAScript test --- .../declarative/qmlecmascript/data/attachedProperty.qml | 11 +++++++++++ tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/auto/declarative/qmlecmascript/data/attachedProperty.qml diff --git a/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml new file mode 100644 index 0000000..c5088e3 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +MyQmlObject { + id: Me + property int a: MyQmlObject.value + property int b: Namespace.MyQmlObject.value + property int c: Me.Namespace.MyQmlObject.value + property int d: Me.Namespace.MyQmlObject.value +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index d5d20b6..eca4b92 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -44,6 +44,7 @@ private slots: void objectPropertiesTriggerReeval(); void deferredProperties(); void extensionObjects(); + void attachedProperties(); void enums(); void valueTypeFunctions(); void constantsOverrideBindings(); @@ -379,6 +380,19 @@ void tst_qmlecmascript::extensionObjects() QCOMPARE(object->baseProperty(), 92); } +void tst_qmlecmascript::attachedProperties() +{ + QmlComponent component(&engine, TEST_FILE("attachedProperty.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("a").toInt(), 19); + QCOMPARE(object->property("b").toInt(), 19); + QCOMPARE(object->property("c").toInt(), 19); + QCOMPARE(object->property("d").toInt(), 19); + + // ### Need to test attached property assignment +} + void tst_qmlecmascript::enums() { // Existant enums -- cgit v0.12 From 114adc64fe8deb7d59e608924355f64810f8fe64 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 19:31:12 +1000 Subject: Fix attached properties/enums from ecmascript --- src/declarative/qml/qmlcontextscriptclass.cpp | 3 +- src/declarative/qml/qmlobjectscriptclass.cpp | 30 +++++++++++++++++-- src/declarative/qml/qmlobjectscriptclass_p.h | 7 ++++- src/declarative/qml/qmltypenamescriptclass.cpp | 41 ++++++++++++++------------ src/declarative/qml/qmltypenamescriptclass_p.h | 5 ++-- 5 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 4b149f7..8f45870 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -104,7 +104,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = - ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags); + ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, + QmlObjectScriptClass::SkipAttachedProperties); if (rv) { lastDefaultObject = ii; diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 33fd409..7c7b13f 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -42,7 +42,9 @@ #include "qmlobjectscriptclass_p.h" #include #include +#include #include +#include QT_BEGIN_NAMESPACE @@ -94,10 +96,11 @@ QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, - QScriptClass::QueryFlags flags) + QScriptClass::QueryFlags flags, QueryMode mode) { Q_UNUSED(flags); lastData = 0; + lastTNData = 0; if (name == m_destroyId.identifier || name == m_toStringId.identifier) @@ -107,6 +110,22 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return 0; QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); + + if (mode == IncludeAttachedProperties) { + QmlContext *evalContext = enginePrivate->currentExpression->context(); + QmlContextPrivate *cp = QmlContextPrivate::get(evalContext); + // ### Check for attached properties + + if (cp->imports) { + QmlTypeNameCache::Data *data = cp->imports->data(name); + if (data) { + lastTNData = data; + return QScriptClass::HandlesReadAccess; + } + } + + } + QmlPropertyCache *cache = 0; QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); if (ddata) @@ -150,7 +169,14 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); - if (lastData->flags & QmlPropertyCache::Data::IsFunction) { + if (lastTNData) { + + if (lastTNData->type) + return enginePriv->typeNameClass->newObject(obj, lastTNData->type); + else + return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace); + + } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) { // ### Optimize QScriptValue sobj = scriptEngine->newQObject(obj); return sobj.property(toString(name)); diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index 6406f0d..6de63ca 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -56,6 +56,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -71,8 +72,11 @@ public: QScriptValue newQObject(QObject *); QObject *toQObject(const QScriptValue &) const; + enum QueryMode { IncludeAttachedProperties, SkipAttachedProperties }; + QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &, - QScriptClass::QueryFlags flags); + QScriptClass::QueryFlags flags, + QueryMode = IncludeAttachedProperties); QScriptValue property(QObject *, const Identifier &); void setProperty(QObject *, const Identifier &name, const QScriptValue &); @@ -85,6 +89,7 @@ protected: virtual QObject *toQObject(Object *, bool *ok = 0); private: + QmlTypeNameCache::Data *lastTNData; QmlPropertyCache::Data *lastData; QmlPropertyCache::Data local; diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index 61b57c4..4e1ac4b 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -46,8 +46,8 @@ QT_BEGIN_NAMESPACE struct TypeNameData : public QScriptDeclarativeClass::Object { - TypeNameData(QObject *o, QmlType *t) : object(o), type(t), typeNamespace(0) {} - TypeNameData(QObject *o, QmlTypeNameCache *n) : object(o), type(0), typeNamespace(n) { + TypeNameData(QObject *o, QmlType *t, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {} + TypeNameData(QObject *o, QmlTypeNameCache *n, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) { if (typeNamespace) typeNamespace->addref(); } ~TypeNameData() { @@ -57,6 +57,7 @@ struct TypeNameData : public QScriptDeclarativeClass::Object { QObject *object; QmlType *type; QmlTypeNameCache *typeNamespace; + QmlTypeNameScriptClass::TypeNameMode mode; }; QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine) @@ -69,21 +70,20 @@ QmlTypeNameScriptClass::~QmlTypeNameScriptClass() { } -QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type) +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type, TypeNameMode mode) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type)); + return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode)); } -QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns) +QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns, TypeNameMode mode) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns)); + return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode)); } - QScriptClass::QueryFlags QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, QScriptClass::QueryFlags flags) @@ -113,15 +113,17 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, if (strName.at(0).isUpper()) { // Must be an enum - // ### Optimize - const char *enumName = strName.toUtf8().constData(); - const QMetaObject *metaObject = data->type->baseMetaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - int value = e.keyToValue(enumName); - if (value != -1) { - enumValue = value; - return QScriptClass::HandlesReadAccess; + if (data->mode == IncludeEnums) { + // ### Optimize + const char *enumName = strName.toUtf8().constData(); + const QMetaObject *metaObject = data->type->baseMetaObject(); + for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { + QMetaEnum e = metaObject->enumerator(ii); + int value = e.keyToValue(enumName); + if (value != -1) { + enumValue = value; + return QScriptClass::HandlesReadAccess; + } } } return 0; @@ -129,7 +131,8 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, // Must be an attached property object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); if (!object) return 0; - return ep->objectClass->queryProperty(object, name, flags); + return ep->objectClass->queryProperty(object, name, flags, + QmlObjectScriptClass::SkipAttachedProperties); } } @@ -140,9 +143,9 @@ QScriptValue QmlTypeNameScriptClass::property(Object *obj, const Identifier &nam { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); if (type) { - return newObject(object, type); + return newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode); } else if (object) { - return ep->objectClass->property(((TypeNameData *)obj)->object, name); + return ep->objectClass->property(object, name); } else { return QScriptValue(enumValue); } diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h index 3bd51e6..d8112d2 100644 --- a/src/declarative/qml/qmltypenamescriptclass_p.h +++ b/src/declarative/qml/qmltypenamescriptclass_p.h @@ -67,8 +67,9 @@ public: QmlTypeNameScriptClass(QmlEngine *); ~QmlTypeNameScriptClass(); - QScriptValue newObject(QObject *, QmlType *); - QScriptValue newObject(QObject *, QmlTypeNameCache *); + enum TypeNameMode { IncludeEnums, ExcludeEnums }; + QScriptValue newObject(QObject *, QmlType *, TypeNameMode = IncludeEnums); + QScriptValue newObject(QObject *, QmlTypeNameCache *, TypeNameMode = IncludeEnums); protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, -- cgit v0.12 From 43d3c9127e36b8f3134a173736d63140b381899f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 2 Oct 2009 23:51:09 +1000 Subject: Fix test failures --- src/declarative/qml/qmlbinding.h | 1 + src/declarative/qml/qmlcontextscriptclass.cpp | 2 +- src/declarative/qml/qmlexpression.cpp | 20 ++++++-------------- src/declarative/qml/qmlmetaproperty.cpp | 16 +++++++++++----- src/declarative/qml/qmlmetaproperty_p.h | 1 + src/declarative/qml/qmlobjectscriptclass.cpp | 11 +++++++---- src/declarative/qml/qmlpropertycache.cpp | 2 ++ src/declarative/qml/qmlvaluetypescriptclass.cpp | 2 +- 8 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index 675917d..e3a297c 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -73,6 +73,7 @@ public: private: friend class QmlDeclarativeData; friend class QmlMetaProperty; + friend class QmlMetaPropertyPrivate; friend class QmlVME; QObject *m_object; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 8f45870..226c34c 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -146,7 +146,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data()); } else { QVariant value = cp->propertyValues.at(lastPropertyIndex); - return ep->scriptValueFromVariant(value); + rv = ep->scriptValueFromVariant(value); } ep->capturedProperties << diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index adf5261..61c14a9 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -296,13 +296,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QList list; for (int ii = 0; ii < length; ++ii) { QScriptValue arrayItem = svalue.property(ii); - QObject *d = - qvariant_cast(arrayItem.data().toVariant()); - if (d) { - list << d; - } else { - list << 0; - } + QObject *d = arrayItem.toQObject(); + list << d; } rv = QVariant::fromValue(list); } @@ -316,13 +311,10 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) !svalue.isQMetaObject() && !svalue.isQObject() && !svalue.isRegExp()) { - QScriptValue objValue = svalue.data(); - if (objValue.isValid()) { - QVariant var = objValue.toVariant(); - if (var.userType() >= (int)QVariant::UserType && - QmlMetaType::isObject(var.userType())) - rv = var; - } + + QObject *o = svalue.toQObject(); + if (o) + return qVariantFromValue(o); } if (rv.isNull()) rv = svalue.toVariant(); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 477377e..155b34a 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -564,14 +564,20 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const if (!isProperty() || (type() & Attached) || !d->object) return 0; - QmlDeclarativeData *data = - QmlDeclarativeData::get(d->object, 0 != newBinding); + d->setBinding(d->object, d->core, newBinding); +} + +QmlAbstractBinding * +QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core, + QmlAbstractBinding *newBinding) +{ + QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding); - if (data && data->hasBindingBit(d->core.coreIndex)) { + if (data && data->hasBindingBit(core.coreIndex)) { QmlAbstractBinding *binding = data->bindings; while (binding) { // ### This wont work for value types - if (binding->propertyIndex() == d->core.coreIndex) { + if (binding->propertyIndex() == core.coreIndex) { binding->setEnabled(false); if (newBinding) @@ -1124,7 +1130,7 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->core.load(p); d->valueTypeCoreIdx = valueTypeIdx; - d->valueTypePropType = p.userType(); + d->valueTypePropType = p2.userType(); } else if (type & Property) { QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0; diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 729236b..00b9c3a 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -101,6 +101,7 @@ public: QVariant readValueProperty(); void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); + static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *); static quint32 saveValueType(int, int); static quint32 saveProperty(int); diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 7c7b13f..2d5991c 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -45,6 +45,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -181,6 +182,11 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name QScriptValue sobj = scriptEngine->newQObject(obj); return sobj.property(toString(name)); } else { + if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { + enginePriv->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + } + if ((uint)lastData->propType < QVariant::UserType) { QmlValueType *valueType = enginePriv->valueTypes[lastData->propType]; if (valueType) @@ -188,10 +194,6 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name } QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); - if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { - enginePriv->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); - } if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { QObject *rv = *(QObject **)var.constData(); @@ -223,6 +225,7 @@ void QmlObjectScriptClass::setProperty(QObject *obj, // ### Can well known types be optimized? QVariant v = QmlScriptClass::toVariant(engine, value); + delete QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0); QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context()); } diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index d7b087b..300bbf6 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE void QmlPropertyCache::Data::load(const QMetaProperty &p) { propType = p.userType(); + if (propType == QVariant::LastType) + propType = qMetaTypeId(); coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); name = QLatin1String(p.name()); diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 503d64f..6fd674a 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -112,7 +112,7 @@ QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, QMetaProperty p = ref.type->metaObject()->property(id); QVariant rv = p.read(ref.type); - return static_cast(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv); + return static_cast(QObjectPrivate::get(engine))->scriptValueFromVariant(rv); } void QmlValueTypeScriptClass::setProperty(QScriptValue &object, -- cgit v0.12 From b2c1ddf00ba2c3395dbfca417540153ea173a870 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Sat, 3 Oct 2009 00:08:03 +1000 Subject: Use QMetaObject::indexOfProperty() This is both more efficient, and allows the creation of dynamic properties. --- src/declarative/qml/qmlpropertycache.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 300bbf6..63ce00c 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -111,14 +111,10 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, QmlPropertyCache::Data rv; - int propCount = metaObject->propertyCount(); - for (int ii = propCount - 1; ii >= 0; --ii) { - QMetaProperty p = metaObject->property(ii); - QString propName = QLatin1String(p.name()); - if (propName == property) { - rv.load(p); - return rv; - } + int idx = metaObject->indexOfProperty(property.toUtf8()); + if (idx != -1) { + rv.load(metaObject->property(idx)); + return rv; } int methodCount = metaObject->methodCount(); -- cgit v0.12 From ff93f4ef4a0effef760964e32cdb77049f19f8ad Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 5 Oct 2009 15:12:21 +1100 Subject: Compile against updated JSC --- .../JavaScriptCore/runtime/Executable.cpp | 20 +++++++++++------ .../JavaScriptCore/runtime/Executable.h | 1 + src/script/api/qscriptengine.cpp | 26 +++++++++++++++------- src/script/bridge/qscriptdeclarativeclass.cpp | 4 ++-- src/script/bridge/qscriptdeclarativeobject.cpp | 8 +++---- src/script/bridge/qscriptdeclarativeobject_p.h | 7 +++--- 6 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp index 5e79794..3df5a84 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp @@ -59,13 +59,8 @@ FunctionExecutable::~FunctionExecutable() delete m_codeBlock; } -JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +void EvalExecutable::compile(ExecState*exec, RefPtr &evalNode, ScopeChainNode* scopeChainNode) { - int errLine; - UString errMsg; - RefPtr evalNode = exec->globalData().parser->parse(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg); - if (!evalNode) - return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url()); recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine()); ScopeChain scopeChain(scopeChainNode); @@ -75,7 +70,18 @@ JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNod m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()); OwnPtr generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock)); generator->generate(); - +} + +JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + int errLine; + UString errMsg; + RefPtr evalNode = exec->globalData().parser->parse(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg); + if (!evalNode) + return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url()); + + compile(exec, evalNode, scopeChainNode); + evalNode->destroyData(); return 0; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h index f3003dd..8d6a668 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h @@ -155,6 +155,7 @@ namespace JSC { } JSObject* compile(ExecState*, ScopeChainNode*); + void compile(ExecState*, RefPtr &, ScopeChainNode*); ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); static PassRefPtr create(const SourceCode& source) { return adoptRef(new EvalExecutable(source)); } diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 7256f27..2bb6eae 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -344,6 +344,7 @@ class QScriptProgramPrivate { public: QScriptProgramPrivate() : refcount(1), hasException(false) { } + ~QScriptProgramPrivate() { if (evalNode) evalNode->destroyData(); } void addref() { ++refcount; } void release() { if (--refcount) delete this; } @@ -2143,15 +2144,17 @@ QScriptProgram QScriptEngine::compile(const QString &program, const QString &fil QBoolBlocker inEval(d->inEval, true); currentContext()->activationObject(); //force the creation of a context for native function; + JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + JSC::UString jscProgram = program; JSC::UString jscFileName = fileName; JSC::ExecState* exec = d->currentFrame; - + WTF::PassRefPtr provider + = QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d); + intptr_t sourceId = provider->asID(); JSC::SourceCode &source = rv.d->source; - source = JSC::makeSource(jscProgram, jscFileName, lineNumber); + source = JSC::SourceCode(provider, lineNumber); //after construction of SourceCode provider variable will be null. - intptr_t sourceId = source.provider()->asID(); - JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); if (debugger) debugger->evaluateStart(sourceId); @@ -2161,9 +2164,9 @@ QScriptProgram QScriptEngine::compile(const QString &program, const QString &fil int errorLine; JSC::UString errorMessage; WTF::RefPtr &evalNode = rv.d->evalNode; - evalNode = exec->globalData().parser->parse(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage); + evalNode = exec->globalData().parser->parse(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, source, &errorLine, &errorMessage); if (!evalNode) { - JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0); + JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), source.provider()->url()); exec->setException(exceptionValue); if (debugger) { @@ -2195,10 +2198,12 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram &program) QBoolBlocker inEval(d->inEval, true); currentContext()->activationObject(); //force the creation of a context for native function; + JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + JSC::ExecState* exec = d->currentFrame; intptr_t sourceId = program.d->source.provider()->asID(); - JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + if (debugger) debugger->evaluateStart(sourceId); @@ -2207,11 +2212,16 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram &program) WTF::RefPtr &evalNode = program.d->evalNode; + JSC::EvalExecutable executable(program.d->source); + executable.compile(exec, evalNode, exec->scopeChain()); + JSC::JSValue thisValue = d->thisForContext(exec); JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSC::JSValue exceptionValue; d->timeoutChecker()->setShouldAbort(false); - JSC::JSValue result = exec->interpreter()->execute(evalNode.get(), exec, thisObject, exec->scopeChain(), &exceptionValue); + if (d->processEventsInterval > 0) + d->timeoutChecker()->reset(); + JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue); if (d->timeoutChecker()->shouldAbort()) { if (d->abortResult.isError()) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 62c1afc..b990e33 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -110,7 +110,7 @@ QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine, QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return 0; QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); @@ -122,7 +122,7 @@ QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return 0; QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index aa811d1..ef77de0 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -149,9 +149,9 @@ bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* objec return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); } -void DeclarativeObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState *exec, - JSC::PropertyNameArray &propertyNames, - unsigned listedAttributes) +void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + bool includeNonEnumerable) { QStringList properties = m_class->propertyNames(m_object); for (int ii = 0; ii < properties.count(); ++ii) { @@ -159,7 +159,7 @@ void DeclarativeObjectDelegate::getPropertyNames(QScriptObject* object, JSC::Exe propertyNames.add(JSC::Identifier(exec, name)); } - QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); } JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData) diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h index ccb07bc..9c14774 100644 --- a/src/script/bridge/qscriptdeclarativeobject_p.h +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -55,6 +55,7 @@ #include +#include "config.h" #include "qscriptobject_p.h" #include "qscriptdeclarativeclass_p.h" @@ -88,9 +89,9 @@ public: virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, - JSC::PropertyNameArray&, - unsigned listedAttributes = JSC::Structure::Prototype); + virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, + JSC::PropertyNameArray&, + bool includeNonEnumerable = false); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); -- cgit v0.12 From c4a7ff8d05c157c9ad628554b94d62a03b69f584 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 5 Oct 2009 16:05:42 +1000 Subject: Add scope auto test --- .../auto/declarative/qmlecmascript/data/scope.qml | 42 ++++++++++++++++++++++ .../qmlecmascript/tst_qmlecmascript.cpp | 18 ++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/auto/declarative/qmlecmascript/data/scope.qml diff --git a/tests/auto/declarative/qmlecmascript/data/scope.qml b/tests/auto/declarative/qmlecmascript/data/scope.qml new file mode 100644 index 0000000..87155d1 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scope.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Item { + id: Root + + property int a: 1 + property int binding: a + property string binding2: a + "Test" + property int binding3: myFunction() + property int binding4: myNestedFunction() + + Script { + function myFunction() { + return a; + } + } + + Item { + id: NestedObject + + Script { + function myNestedFunction() { + return a; + } + } + + property int a: 2 + property int binding: a + property string binding2: a + "Test" + property int binding3: myFunction() + property int binding4: myNestedFunction() + } + + property alias test1: Root.binding + property alias test2: NestedObject.binding + property alias test3: Root.binding2 + property alias test4: NestedObject.binding2 + property alias test5: Root.binding3 + property alias test6: NestedObject.binding3 + property alias test7: Root.binding4 + property alias test8: NestedObject.binding4 +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index eca4b92..00c3475 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -51,6 +51,7 @@ private slots: void outerBindingOverridesInnerBinding(); void aliasPropertyAndBinding(); void nonExistantAttachedObject(); + void scope(); private: QmlEngine engine; @@ -525,6 +526,23 @@ void tst_qmlecmascript::nonExistantAttachedObject() QVERIFY(object != 0); } +void tst_qmlecmascript::scope() +{ + QmlComponent component(&engine, TEST_FILE("scope.qml")); + qWarning() << component.errors(); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 1); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toString(), QString("1Test")); + QCOMPARE(object->property("test4").toString(), QString("2Test")); + QCOMPARE(object->property("test5").toInt(), 1); + QCOMPARE(object->property("test6").toInt(), 1); + QCOMPARE(object->property("test7").toInt(), 2); + QCOMPARE(object->property("test8").toInt(), 2); +} + /* Confirm bindings and alias properties can coexist. -- cgit v0.12 From b411c4db37bcbb5152bf8e8b225e259c05c46b59 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 5 Oct 2009 18:37:48 +1000 Subject: Support all variant types as signal parameters --- src/declarative/qml/qmlmetatype.cpp | 206 +++++++++++++++++++-- .../qmlecmascript/data/signalParameterTypes.qml | 16 ++ .../qmlecmascript/tst_qmlecmascript.cpp | 16 +- 3 files changed, 219 insertions(+), 19 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 14d85ff..663e8e0 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -929,6 +929,30 @@ QList QmlMetaType::qmlTypes() return data->nameToType.values(); } +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include + /*! Copies \a copy into \a data, assuming they both are of type \a type. If \a copy is zero, a default type is copied. Returns true if the copy was @@ -988,7 +1012,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QChar: *static_cast(data) = *static_cast(copy); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QVariantMap: *static_cast(data) = *static_cast(copy); return true; @@ -998,7 +1021,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QVariantList: *static_cast(data) = *static_cast(copy); return true; -#endif case QMetaType::QByteArray: *static_cast(data) = *static_cast(copy); return true; @@ -1008,11 +1030,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QStringList: *static_cast(data) = *static_cast(copy); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QBitArray: *static_cast(data) = *static_cast(copy); return true; -#endif case QMetaType::QDate: *static_cast(data) = *static_cast(copy); return true; @@ -1022,15 +1042,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QDateTime: *static_cast(data) = *static_cast(copy); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QUrl: *static_cast(data) = *static_cast(copy); return true; -#endif case QMetaType::QLocale: *static_cast(data) = *static_cast(copy); return true; -#ifndef QT_NO_GEOM_VARIANT case QMetaType::QRect: *static_cast(data) = *static_cast(copy); return true; @@ -1058,7 +1075,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QVector3D: *static_cast(data) = *static_cast(copy); return true; -#endif #ifndef QT_NO_REGEXP case QMetaType::QRegExp: *static_cast(data) = *static_cast(copy); @@ -1066,8 +1082,90 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) #endif case QMetaType::Void: return true; + + +#ifdef QT3_SUPPORT + case QMetaType::QColorGroup: + *static_cast(data) = *static_cast(copy); + return true; +#endif + + case QMetaType::QFont: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QPixmap: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QBrush: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QColor: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QPalette: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QIcon: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QImage: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QPolygon: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QRegion: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QBitmap: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QCursor: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QSizePolicy: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QKeySequence: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QPen: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QTextLength: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QTextFormat: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QMatrix: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QTransform: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QMatrix4x4: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QVector2D: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QVector4D: + *static_cast(data) = *static_cast(copy); + return true; + case QMetaType::QQuaternion: + *static_cast(data) = *static_cast(copy); + return true; + default: - ; + if (type == qMetaTypeId()) { + *static_cast(data) = *static_cast(copy); + return true; + } else if (typeCategory(type) != Unknown) { + *static_cast(data) = *static_cast(copy); + return true; + } + break; } } else { switch(type) { @@ -1118,7 +1216,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QChar: *static_cast(data) = NS(QChar)(); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QVariantMap: *static_cast(data) = NS(QVariantMap)(); return true; @@ -1128,7 +1225,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QVariantList: *static_cast(data) = NS(QVariantList)(); return true; -#endif case QMetaType::QByteArray: *static_cast(data) = NS(QByteArray)(); return true; @@ -1138,11 +1234,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QStringList: *static_cast(data) = NS(QStringList)(); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QBitArray: *static_cast(data) = NS(QBitArray)(); return true; -#endif case QMetaType::QDate: *static_cast(data) = NS(QDate)(); return true; @@ -1152,15 +1246,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QDateTime: *static_cast(data) = NS(QDateTime)(); return true; -#ifndef QT_BOOTSTRAPPED case QMetaType::QUrl: *static_cast(data) = NS(QUrl)(); return true; -#endif case QMetaType::QLocale: *static_cast(data) = NS(QLocale)(); return true; -#ifndef QT_NO_GEOM_VARIANT case QMetaType::QRect: *static_cast(data) = NS(QRect)(); return true; @@ -1188,7 +1279,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) case QMetaType::QVector3D: *static_cast(data) = NS(QVector3D)(); return true; -#endif #ifndef QT_NO_REGEXP case QMetaType::QRegExp: *static_cast(data) = NS(QRegExp)(); @@ -1196,8 +1286,88 @@ bool QmlMetaType::copy(int type, void *data, const void *copy) #endif case QMetaType::Void: return true; + +#ifdef QT3_SUPPORT + case QMetaType::QColorGroup: + *static_cast(data) = NS(QColorGroup)(); + return true; +#endif + + case QMetaType::QFont: + *static_cast(data) = NS(QFont)(); + return true; + case QMetaType::QPixmap: + *static_cast(data) = NS(QPixmap)(); + return true; + case QMetaType::QBrush: + *static_cast(data) = NS(QBrush)(); + return true; + case QMetaType::QColor: + *static_cast(data) = NS(QColor)(); + return true; + case QMetaType::QPalette: + *static_cast(data) = NS(QPalette)(); + return true; + case QMetaType::QIcon: + *static_cast(data) = NS(QIcon)(); + return true; + case QMetaType::QImage: + *static_cast(data) = NS(QImage)(); + return true; + case QMetaType::QPolygon: + *static_cast(data) = NS(QPolygon)(); + return true; + case QMetaType::QRegion: + *static_cast(data) = NS(QRegion)(); + return true; + case QMetaType::QBitmap: + *static_cast(data) = NS(QBitmap)(); + return true; + case QMetaType::QCursor: + *static_cast(data) = NS(QCursor)(); + return true; + case QMetaType::QSizePolicy: + *static_cast(data) = NS(QSizePolicy)(); + return true; + case QMetaType::QKeySequence: + *static_cast(data) = NS(QKeySequence)(); + return true; + case QMetaType::QPen: + *static_cast(data) = NS(QPen)(); + return true; + case QMetaType::QTextLength: + *static_cast(data) = NS(QTextLength)(); + return true; + case QMetaType::QTextFormat: + *static_cast(data) = NS(QTextFormat)(); + return true; + case QMetaType::QMatrix: + *static_cast(data) = NS(QMatrix)(); + return true; + case QMetaType::QTransform: + *static_cast(data) = NS(QTransform)(); + return true; + case QMetaType::QMatrix4x4: + *static_cast(data) = NS(QMatrix4x4)(); + return true; + case QMetaType::QVector2D: + *static_cast(data) = NS(QVector2D)(); + return true; + case QMetaType::QVector4D: + *static_cast(data) = NS(QVector4D)(); + return true; + case QMetaType::QQuaternion: + *static_cast(data) = NS(QQuaternion)(); + return true; default: - ; + if (type == qMetaTypeId()) { + *static_cast(data) = NS(QVariant)(); + return true; + } else if (typeCategory(type) != Unknown) { + *static_cast(data) = 0; + return true; + } + break; } } diff --git a/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml new file mode 100644 index 0000000..42d26a1 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 + +MyQmlObject +{ + id: Root + property int intProperty + property real realProperty + property color colorProperty + property var variantProperty + + signal mySignal(int a, real b, color c, var d) + + onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; } + + onBasicSignal: Root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1)) +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 00c3475..65f7021 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -52,6 +52,7 @@ private slots: void aliasPropertyAndBinding(); void nonExistantAttachedObject(); void scope(); + void signalParameterTypes(); private: QmlEngine engine; @@ -529,7 +530,6 @@ void tst_qmlecmascript::nonExistantAttachedObject() void tst_qmlecmascript::scope() { QmlComponent component(&engine, TEST_FILE("scope.qml")); - qWarning() << component.errors(); QObject *object = component.create(); QVERIFY(object != 0); @@ -543,6 +543,20 @@ void tst_qmlecmascript::scope() QCOMPARE(object->property("test8").toInt(), 2); } +void tst_qmlecmascript::signalParameterTypes() +{ + QmlComponent component(&engine, TEST_FILE("signalParameterTypes.qml")); + MyQmlObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + emit object->basicSignal(); + + QCOMPARE(object->property("intProperty").toInt(), 10); + QCOMPARE(object->property("realProperty").toReal(), 19.2); + QVERIFY(object->property("colorProperty").value() == QColor(255, 255, 0, 255)); + QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255))); +} + /* Confirm bindings and alias properties can coexist. -- cgit v0.12 From 54e8e22a49148b089fd02895ead5c27aaf62e18e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 10:36:07 +1000 Subject: Share QScriptValue's where possible Also add an autotest for object comparisons --- src/declarative/qml/qmldeclarativedata_p.h | 2 ++ src/declarative/qml/qmlobjectscriptclass.cpp | 11 ++++++++++- .../qmlecmascript/data/objectsCompareAsEqual.qml | 15 +++++++++++++++ .../declarative/qmlecmascript/tst_qmlecmascript.cpp | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h index b4c87b8..f6ecc3d 100644 --- a/src/declarative/qml/qmldeclarativedata_p.h +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -54,6 +54,7 @@ // #include +#include QT_BEGIN_NAMESPACE @@ -86,6 +87,7 @@ public: QHash *attachedProperties; + QScriptValue scriptValue; QmlPropertyCache *propertyCache; static QmlDeclarativeData *get(const QObject *object, bool create = false) { diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 2d5991c..330eddd 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -80,7 +80,16 @@ QScriptValue QmlObjectScriptClass::newQObject(QObject *object) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ObjectData(object)); + QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true); + + if (!ddata->scriptValue.isValid()) { + ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object)); + return ddata->scriptValue; + } else if (ddata->scriptValue.engine() == QmlEnginePrivate::getScriptEngine(engine)) { + return ddata->scriptValue; + } else { + return newObject(scriptEngine, this, new ObjectData(object)); + } } QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const diff --git a/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml new file mode 100644 index 0000000..2526576 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml @@ -0,0 +1,15 @@ +import Qt 4.6 + +Item { + id: Root + + property var item: Child + Item { id: Child } + + property bool test1: Child == Child + property bool test2: Child.parent == Root + property bool test3: Root != Child + property bool test4: item == Child + property bool test5: item != Root +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 65f7021..15bfe24 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -53,6 +53,7 @@ private slots: void nonExistantAttachedObject(); void scope(); void signalParameterTypes(); + void objectsCompareAsEqual(); private: QmlEngine engine; @@ -543,6 +544,10 @@ void tst_qmlecmascript::scope() QCOMPARE(object->property("test8").toInt(), 2); } +/* +Tests that "any" type passes through a synthesized signal parameter. This +is essentially a test of QmlMetaType::copy() +*/ void tst_qmlecmascript::signalParameterTypes() { QmlComponent component(&engine, TEST_FILE("signalParameterTypes.qml")); @@ -558,6 +563,22 @@ void tst_qmlecmascript::signalParameterTypes() } /* +Test that two JS objects for the same QObject compare as equal. +*/ +void tst_qmlecmascript::objectsCompareAsEqual() +{ + QmlComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + QCOMPARE(object->property("test5").toBool(), true); +} + +/* Confirm bindings and alias properties can coexist. Tests for a regression where the binding would not reevaluate. -- cgit v0.12 From 51e9a75d2d26f2f7ad4cf11a730c8d6e12dc3886 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 15:01:28 +1000 Subject: Improve scope autotest --- tests/auto/declarative/qmlecmascript/data/ScopeObject.qml | 14 ++++++++++++++ tests/auto/declarative/qmlecmascript/data/scope.qml | 6 ++++++ tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 tests/auto/declarative/qmlecmascript/data/ScopeObject.qml diff --git a/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml new file mode 100644 index 0000000..b7bec63 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml @@ -0,0 +1,14 @@ +import Qt 4.6 + +Item { + property int a: 3 + property int binding: myFunction(); + property int binding2: myCompFunction(); + + Script { + function myCompFunction() { + return a; + } + } +} + diff --git a/tests/auto/declarative/qmlecmascript/data/scope.qml b/tests/auto/declarative/qmlecmascript/data/scope.qml index 87155d1..80222c8 100644 --- a/tests/auto/declarative/qmlecmascript/data/scope.qml +++ b/tests/auto/declarative/qmlecmascript/data/scope.qml @@ -31,6 +31,10 @@ Item { property int binding4: myNestedFunction() } + ScopeObject { + id: CompObject + } + property alias test1: Root.binding property alias test2: NestedObject.binding property alias test3: Root.binding2 @@ -39,4 +43,6 @@ Item { property alias test6: NestedObject.binding3 property alias test7: Root.binding4 property alias test8: NestedObject.binding4 + property alias test9: CompObject.binding + property alias test10: CompObject.binding2 } diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 15bfe24..c69528a 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -542,6 +542,8 @@ void tst_qmlecmascript::scope() QCOMPARE(object->property("test6").toInt(), 1); QCOMPARE(object->property("test7").toInt(), 2); QCOMPARE(object->property("test8").toInt(), 2); + QCOMPARE(object->property("test9").toInt(), 1); + QCOMPARE(object->property("test10").toInt(), 3); } /* -- cgit v0.12 From 00da55bcd3ab574073b34ae4b558a40722a94c47 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 15:02:13 +1000 Subject: Add a QScriptEngine::pushCleanContext() method --- src/script/api/qscriptengine.cpp | 41 ++++++++++++++++++++++++++++++++++++++-- src/script/api/qscriptengine.h | 1 + src/script/api/qscriptengine_p.h | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 2bb6eae..785d80f 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -2400,6 +2400,35 @@ QScriptContext *QScriptEngine::pushContext() return d->contextForFrame(newFrame); } +/*! + Enters a new execution context and returns the associated + QScriptContext object. + + Once you are done with the context, you should call popContext() to + restore the old context. + + By default, the `this' object of the new context is the Global Object. + The context's \l{QScriptContext::callee()}{callee}() will be invalid. + + Unlike pushContext(), the default scope chain is reset to include + only the global object and the QScriptContext's activation object. + + \sa popContext() +*/ +QScriptContext *QScriptEngine::pushCleanContext() +{ + Q_D(QScriptEngine); + + JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject, + JSC::ArgList(), /*callee = */0, false, true); + + if (agent()) + agent()->contextPush(); + + return d->contextForFrame(newFrame); +} + + /*! \internal push a context for a native function. JSC native function doesn't have different stackframe or context. so we need to create one. @@ -2411,7 +2440,8 @@ QScriptContext *QScriptEngine::pushContext() return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow */ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject, - const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor) + const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor, + bool clearScopeChain) { JSC::JSValue thisObject = _thisObject; if (calledAsConstructor) { @@ -2445,7 +2475,14 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV for (it = args.begin(); it != args.end(); ++it) newCallFrame[++dst] = *it; newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; - newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); + + if (!clearScopeChain) { + newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); + } else { + JSC::JSObject *jscObject = originalGlobalObject(); + JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject); + newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); + } } else { setContextFlags(newCallFrame, flags); #if ENABLE(JIT) diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 71266cc..cd86aca 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -182,6 +182,7 @@ public: QScriptContext *currentContext() const; QScriptContext *pushContext(); + QScriptContext *pushCleanContext(); void popContext(); bool canEvaluate(const QString &program) const; diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 5f31054..7218ee1 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -162,7 +162,7 @@ public: static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame); JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args, - JSC::JSObject *callee, bool calledAsConstructor = false); + JSC::JSObject *callee, bool calledAsConstructor = false, bool clearScopeChain = false); void popContext(); void mark(JSC::MarkStack& markStack); -- cgit v0.12 From 9e4b877430a6811079d209656587ea228334ed34 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 15:30:59 +1000 Subject: Export the active QScriptContext during a callback Clearly the API needs work :) --- src/script/bridge/qscriptdeclarativeclass.cpp | 50 ++++++++++++++++++++++++-- src/script/bridge/qscriptdeclarativeclass_p.h | 4 +++ src/script/bridge/qscriptdeclarativeobject.cpp | 7 ++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index b990e33..a7667cb 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -78,14 +79,14 @@ QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentif class QScriptDeclarativeClassPrivate { public: - QScriptDeclarativeClassPrivate() {} + QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0) {} QScriptEngine *engine; QScriptDeclarativeClass *q_ptr; }; QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) -: d_ptr(new QScriptDeclarativeClassPrivate) +: context(0), d_ptr(new QScriptDeclarativeClassPrivate) { Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier)); d_ptr->q_ptr = this; @@ -176,6 +177,51 @@ QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Iden return QScriptValue(); } +/* +Returns the scope chain entry \a index from the end. This is equivalent to: + context->scopeChain().at(context->scopeChain.length() - 1 - index) +*/ +QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index) +{ + context->activationObject(); //ensure the creation of the normal scope for native context + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + + JSC::ScopeChainNode *node = frame->scopeChain(); + JSC::ScopeChainIterator it(node); + + int count = 0; + for (it = node->begin(); it != node->end(); ++it) + ++count; + + if (count < index) + return QScriptValue(); + + count -= index; + + for (it = node->begin(); it != node->end(); ++it) { + + if (count == 0) { + + JSC::JSObject *object = *it; + if (!object) return QScriptValue(); + + if (object->inherits(&QScript::QScriptActivationObject::info) + && (static_cast(object)->delegate() != 0)) { + // Return the object that property access is being delegated to + object = static_cast(object)->delegate(); + } + return engine->scriptValueFromJSCValue(object); + + } else { + --count; + } + + } + + return QScriptValue(); +} + QScriptDeclarativeClass::~QScriptDeclarativeClass() { } diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 07cfad1..0d05ec5 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QScriptDeclarativeClassPrivate; class PersistentIdentifierPrivate; +class QScriptContext; class Q_SCRIPT_EXPORT QScriptDeclarativeClass { public: @@ -75,6 +76,8 @@ public: static QScriptValue function(const QScriptValue &, const Identifier &); static QScriptValue property(const QScriptValue &, const Identifier &); + static QScriptValue scopeChainValue(QScriptContext *, int index); + class Q_SCRIPT_EXPORT PersistentIdentifier { public: @@ -113,6 +116,7 @@ public: virtual QObject *toQObject(Object *, bool *ok = 0); virtual QVariant toVariant(Object *, bool *ok = 0); + QScriptContext *context; protected: QScopedPointer d_ptr; }; diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index ef77de0..ffdebb0 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -87,13 +87,16 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); + m_class->context = reinterpret_cast(exec); QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); if (flags & QScriptClass::HandlesReadAccess) { QScriptValue value = m_class->property(m_object, identifier); + m_class->context = 0; slot.setValue(engine->scriptValueToJSCValue(value)); return true; } + m_class->context = 0; return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); } @@ -105,12 +108,16 @@ void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); + m_class->context = reinterpret_cast(exec); QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesWriteAccess); if (flags & QScriptClass::HandlesWriteAccess) { m_class->setProperty(m_object, identifier, engine->scriptValueFromJSCValue(value)); + m_class->context = 0; return; } + m_class->context = 0; + QScriptObjectDelegate::put(object, exec, propertyName, value, slot); } -- cgit v0.12 From 067b419199b369b6c81fa1ae387257aa87cab20c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 15:31:56 +1000 Subject: Improve scope handling --- src/declarative/qml/qmlcontext.cpp | 11 +---- src/declarative/qml/qmlcontext_p.h | 3 +- src/declarative/qml/qmlcontextscriptclass.cpp | 45 +++++++++++++++++---- src/declarative/qml/qmlcontextscriptclass_p.h | 6 +++ src/declarative/qml/qmlexpression.cpp | 22 +++++----- src/declarative/qml/qmlobjectscriptclass.cpp | 56 ++++++++++++++++---------- src/declarative/qml/qmlobjectscriptclass_p.h | 3 +- src/declarative/qml/qmltypenamescriptclass.cpp | 3 +- src/declarative/util/qmlscript.cpp | 6 +-- 9 files changed, 96 insertions(+), 59 deletions(-) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 968597c..a1eb5de 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -103,16 +103,7 @@ void QmlContextPrivate::init() //set scope chain QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - QScriptValue scopeObj = QmlEnginePrivate::get(engine)->contextClass->newContext(q); - - //### no longer need to push global object once we switch to JSC (test with objects added to globalObject) - //if (parent) - // scopeChain = parent->d_func()->scopeChain; - if (!parent) - scopeChain.append(scriptEngine->globalObject()); - else - scopeChain = parent->d_func()->scopeChain; - scopeChain.prepend(scopeObj); + scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 8fd2e92..22e5895 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -85,14 +85,13 @@ public: bool isInternal; QmlIntegerCache *propertyNames; -// QHash propertyNames; QList propertyValues; int notifyIndex; QObjectList defaultObjects; int highPriorityCount; - QScriptValueList scopeChain; + QScriptValue scriptValue; QList scripts; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 226c34c..6d2c58c 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -72,51 +72,80 @@ QScriptValue QmlContextScriptClass::newContext(QmlContext *context) return newObject(scriptEngine, this, new ContextData(context)); } +QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) +{ + if (scriptClass(v) != this) + return 0; + + ContextData *data = (ContextData *)object(v); + return data->context; +} + +#include QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastContext = 0; + lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; - lastData = 0; QmlContext *bindContext = ((ContextData *)object)->context.data(); if (!bindContext) return 0; + while (bindContext) { + QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + if (rv) return rv; + bindContext = bindContext->parentContext(); + } + + return 0; +} + +QScriptClass::QueryFlags +QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, + QScriptClass::QueryFlags flags) +{ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1; - if (lastPropertyIndex != -1) + if (lastPropertyIndex != -1) { + lastContext = bindContext; return QScriptClass::HandlesReadAccess; + } - if (ep->currentExpression && cp->imports && bindContext == ep->currentExpression->context()) { + if (cp->imports) { QmlTypeNameCache::Data *data = cp->imports->data(name); if (data) { lastData = data; + lastContext = bindContext; return QScriptClass::HandlesReadAccess; } } for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = - ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, - QmlObjectScriptClass::SkipAttachedProperties); + ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); if (rv) { lastDefaultObject = ii; + lastContext = bindContext; return rv; } } for (int ii = 0; ii < cp->scripts.count(); ++ii) { lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) + if (lastFunction.isValid()) { + lastContext = bindContext; return QScriptClass::HandlesReadAccess; + } } return 0; } @@ -125,7 +154,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n { Q_UNUSED(object); - QmlContext *bindContext = ((ContextData *)object)->context.data(); + QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -170,7 +199,7 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, { Q_ASSERT(lastDefaultObject != -1); - QmlContext *bindContext = ((ContextData *)object)->context.data(); + QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index acb8926..761a115 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -69,6 +69,8 @@ public: QScriptValue newContext(QmlContext *); + QmlContext *contextFromValue(const QScriptValue &); + protected: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); @@ -76,8 +78,12 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: + QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags flags); + QmlEngine *engine; + QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; int lastDefaultObject; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 61c14a9..e1c7afe 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -82,17 +82,20 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, int progIdx = *(data + 1); QmlEngine *engine = ctxt->engine(); + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(expression)); } QmlContextPrivate *ctxtPriv = ctxt->d_func(); - QScriptContext *scriptContext = scriptEngine->pushContext(); - for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i) - scriptContext->pushScope(ctxtPriv->scopeChain.at(i)); + QScriptContext *scriptContext = scriptEngine->pushCleanContext(); + scriptContext->pushScope(ctxtPriv->scriptValue); + if (me) + scriptContext->pushScope(ep->objectClass->newQObject(me)); expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); + expressionFunctionValid = true; scriptEngine->popContext(); } @@ -239,9 +242,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QmlContextPrivate *ctxtPriv = context()->d_func(); QmlEngine *engine = context()->engine(); + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - if (me) - ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me); if (secondaryScope) ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, secondaryScope); @@ -250,9 +252,11 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!expressionFunctionValid) { - QScriptContext *scriptContext = scriptEngine->pushContext(); - for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i) - scriptContext->pushScope(ctxtPriv->scopeChain.at(i)); + QScriptContext *scriptContext = scriptEngine->pushCleanContext(); + scriptContext->pushScope(ctxtPriv->scriptValue); + + if (me) + scriptContext->pushScope(ep->objectClass->newQObject(me)); if (expressionRewritten) { expressionFunction = scriptEngine->evaluate(expression, fileName, line); @@ -283,8 +287,6 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) } } - if (me) - ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); if (secondaryScope) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 330eddd..2d69590 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -80,6 +80,9 @@ QScriptValue QmlObjectScriptClass::newQObject(QObject *object) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + if (!object) + return newObject(scriptEngine, this, new ObjectData(object)); + QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true); if (!ddata->scriptValue.isValid()) { @@ -101,12 +104,12 @@ QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { - return queryProperty(toQObject(object), name, flags); + return queryProperty(toQObject(object), name, flags, 0); } QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, - QScriptClass::QueryFlags flags, QueryMode mode) + QScriptClass::QueryFlags flags, QmlContext *evalContext) { Q_UNUSED(flags); lastData = 0; @@ -120,21 +123,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return 0; QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); - - if (mode == IncludeAttachedProperties) { - QmlContext *evalContext = enginePrivate->currentExpression->context(); - QmlContextPrivate *cp = QmlContextPrivate::get(evalContext); - // ### Check for attached properties - - if (cp->imports) { - QmlTypeNameCache::Data *data = cp->imports->data(name); - if (data) { - lastTNData = data; - return QScriptClass::HandlesReadAccess; - } - } - - } + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlPropertyCache *cache = 0; QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); @@ -153,12 +142,35 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, lastData = &local; } - if (!lastData) return 0; + if (lastData) { + QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess; + if (lastData->flags & QmlPropertyCache::Data::IsWritable) + rv |= QScriptClass::HandlesWriteAccess; + return rv; + } + + if (!evalContext && context) { + // Global object, QScriptContext activation object, QmlContext object + QScriptValue scopeNode = scopeChainValue(context, 3); + Q_ASSERT(scopeNode.isValid()); + Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass); + + evalContext = enginePrivate->contextClass->contextFromValue(scopeNode); + } + + if (evalContext) { + QmlContextPrivate *cp = QmlContextPrivate::get(evalContext); + + if (cp->imports) { + QmlTypeNameCache::Data *data = cp->imports->data(name); + if (data) { + lastTNData = data; + return QScriptClass::HandlesReadAccess; + } + } + } - QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess; - if (lastData->flags & QmlPropertyCache::Data::IsWritable) - rv |= QScriptClass::HandlesWriteAccess; - return rv; + return 0; } QScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name) diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index 6de63ca..3fcf009 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -63,6 +63,7 @@ QT_BEGIN_NAMESPACE class QmlEngine; class QScriptContext; class QScriptEngine; +class QmlContext; class QmlObjectScriptClass : public QScriptDeclarativeClass { public: @@ -76,7 +77,7 @@ public: QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &, QScriptClass::QueryFlags flags, - QueryMode = IncludeAttachedProperties); + QmlContext *evalContext); QScriptValue property(QObject *, const Identifier &); void setProperty(QObject *, const Identifier &name, const QScriptValue &); diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp index 4e1ac4b..c0613d1 100644 --- a/src/declarative/qml/qmltypenamescriptclass.cpp +++ b/src/declarative/qml/qmltypenamescriptclass.cpp @@ -131,8 +131,7 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name, // Must be an attached property object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); if (!object) return 0; - return ep->objectClass->queryProperty(object, name, flags, - QmlObjectScriptClass::SkipAttachedProperties); + return ep->objectClass->queryProperty(object, name, flags, 0); } } diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp index 2031a54..5d58f64 100644 --- a/src/declarative/util/qmlscript.cpp +++ b/src/declarative/util/qmlscript.cpp @@ -178,10 +178,8 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s QmlContext *context = qmlContext(q); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - QScriptContext *scriptContext = scriptEngine->pushContext(); - for (int i = context->d_func()->scopeChain.size() - 1; i >= 0; --i) { - scriptContext->pushScope(context->d_func()->scopeChain.at(i)); - } + QScriptContext *scriptContext = scriptEngine->pushCleanContext(); + scriptContext->pushScope(QmlContextPrivate::get(context)->scriptValue); QScriptValue scope = scriptEngine->newObject(); scriptContext->pushScope(scope); -- cgit v0.12 From 3184fbcd858244b5cd171fd0ab32c3ff565e579e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 15:48:32 +1000 Subject: Add tst_qmlecmascript::scriptAccess testcase --- .../auto/declarative/qmlecmascript/data/scriptAccess.js | 7 +++++++ .../declarative/qmlecmascript/data/scriptAccess.qml | 17 +++++++++++++++++ .../declarative/qmlecmascript/tst_qmlecmascript.cpp | 15 +++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptAccess.js create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptAccess.qml diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.js b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js new file mode 100644 index 0000000..c00d285 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js @@ -0,0 +1,7 @@ +var extVariable = 19; + +function extMethod() +{ + return extVariable; +} + diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml new file mode 100644 index 0000000..feb6d16 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml @@ -0,0 +1,17 @@ +import Qt 4.6 + +Item { + Script { + function method() { + return 10; + } + } + + Script { + source: "scriptAccess.js" + } + + property int test1: method() + property int test2: extMethod() + property int test3: extVariable +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index c69528a..15a7860 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -54,6 +54,7 @@ private slots: void scope(); void signalParameterTypes(); void objectsCompareAsEqual(); + void scriptAccess(); private: QmlEngine engine; @@ -600,6 +601,20 @@ void tst_qmlecmascript::aliasPropertyAndBinding() QCOMPARE(object->property("c3").toInt(), 19); } +/* +Tests that only methods of Script {} blocks are exposed. +*/ +void tst_qmlecmascript::scriptAccess() +{ + QmlComponent component(&engine, TEST_FILE("scriptAccess.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 10); + QCOMPARE(object->property("test2").toInt(), 19); + QCOMPARE(object->property("test3").toInt(), 0); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From 50a4a8ec76b98cc860de9b6e6aaf25c87e690eed Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 6 Oct 2009 17:47:14 +1000 Subject: Another test --- .../qmllanguage/data/dynamicObjectProperties.qml | 13 +++++++++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml diff --git a/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml new file mode 100644 index 0000000..e69ccee --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml @@ -0,0 +1,13 @@ +import Test 1.0 +import Qt 4.6 +import Qt 4.6 as Qt + +Object { + property Object objectProperty + property Object objectProperty2 + objectProperty2: Object {} + + property MyComponent myComponentProperty + property MyComponent myComponentProperty2 + myComponentProperty2: MyComponent {} +} diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 1bf98df..3825b62 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -45,6 +45,7 @@ private slots: void idProperty(); void assignSignal(); void dynamicProperties(); + void dynamicObjectProperties(); void dynamicSignalsAndSlots(); void simpleBindings(); void autoComponentCreation(); @@ -404,6 +405,19 @@ void tst_qmllanguage::dynamicProperties() QCOMPARE(object->property("variantProperty"), QVariant(12)); } +// Tests the creation and assignment of dynamic object properties +// ### Not complete +void tst_qmllanguage::dynamicObjectProperties() +{ + QmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0)); + QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0)); +} + // Tests the declaration of dynamic signals and slots void tst_qmllanguage::dynamicSignalsAndSlots() { -- cgit v0.12 From 5584feca163e91588f08b0aa1f3ae2817cd90823 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 7 Oct 2009 09:53:01 +1000 Subject: Auto tests for QmlTimer --- src/declarative/fx/qfxvisualitemmodel.cpp | 38 +++--- src/declarative/util/qmltimer.cpp | 16 ++- tests/auto/declarative/declarative.pro | 5 +- tests/auto/declarative/qmltimer/qmltimer.pro | 5 + tests/auto/declarative/qmltimer/tst_qmltimer.cpp | 141 +++++++++++++++++++++++ 5 files changed, 182 insertions(+), 23 deletions(-) create mode 100644 tests/auto/declarative/qmltimer/qmltimer.pro create mode 100644 tests/auto/declarative/qmltimer/tst_qmltimer.cpp diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index fb1cfcf..b7248ea 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -264,10 +264,10 @@ public: } if (m_roles.count() == 1) m_roleNames.insert(QLatin1String("modelData"), m_roles.at(0)); - } else if (m_modelList) { + } else if (m_listAccessor) { m_roleNames.insert(QLatin1String("modelData"), 0); - if (m_modelList->type() == QmlListAccessor::Instance) { - if (QObject *object = m_modelList->at(0).value()) { + if (m_listAccessor->type() == QmlListAccessor::Instance) { + if (QObject *object = m_listAccessor->at(0).value()) { int count = object->metaObject()->propertyCount(); for (int ii = 1; ii < count; ++ii) { const QMetaProperty &prop = object->metaObject()->property(ii); @@ -330,7 +330,7 @@ public: QFxVisualDataModelData *data(QObject *item); QVariant m_modelVariant; - QmlListAccessor *m_modelList; + QmlListAccessor *m_listAccessor; int modelCount() const { if (m_visualItemModel) @@ -339,8 +339,8 @@ public: return m_listModelInterface->count(); if (m_abstractItemModel) return m_abstractItemModel->rowCount(); - if (m_modelList) - return m_modelList->count(); + if (m_listAccessor) + return m_listAccessor->count(); return 0; } }; @@ -405,7 +405,7 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha static_cast(object()); if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel) - && data->m_model->m_modelList) { + && data->m_model->m_listAccessor) { data->m_model->ensureRoles(); if (data->m_model->m_roleNames.contains(QLatin1String(name))) return QmlOpenMetaObject::createProperty(name, type); @@ -427,16 +427,16 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro static_cast(object()); QString name = QLatin1String(prop.name()); if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel) - && data->m_model->m_modelList) { + && data->m_model->m_listAccessor) { if (name == QLatin1String("modelData")) { - if (data->m_model->m_modelList->type() == QmlListAccessor::Instance) { - QObject *object = data->m_model->m_modelList->at(0).value(); + if (data->m_model->m_listAccessor->type() == QmlListAccessor::Instance) { + QObject *object = data->m_model->m_listAccessor->at(0).value(); return object->metaObject()->property(1).read(object); // the first property after objectName } - return data->m_model->m_modelList->at(data->m_index); + return data->m_model->m_listAccessor->at(data->m_index); } else { // return any property of a single object instance. - QObject *object = data->m_model->m_modelList->at(0).value(); + QObject *object = data->m_model->m_listAccessor->at(0).value(); return object->property(prop.name()); } } else if (data->m_model->m_listModelInterface) { @@ -531,7 +531,7 @@ QFxVisualDataModelParts::QFxVisualDataModelParts(QFxVisualDataModel *parent) QFxVisualDataModelPrivate::QFxVisualDataModelPrivate(QmlContext *ctxt) : m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0) -, m_context(ctxt), m_parts(0), m_modelList(0) +, m_context(ctxt), m_parts(0), m_listAccessor(0) { } @@ -556,8 +556,8 @@ QFxVisualDataModel::QFxVisualDataModel(QmlContext *ctxt) QFxVisualDataModel::~QFxVisualDataModel() { Q_D(QFxVisualDataModel); - if (d->m_modelList) - delete d->m_modelList; + if (d->m_listAccessor) + delete d->m_listAccessor; } QVariant QFxVisualDataModel::model() const @@ -569,8 +569,8 @@ QVariant QFxVisualDataModel::model() const void QFxVisualDataModel::setModel(const QVariant &model) { Q_D(QFxVisualDataModel); - delete d->m_modelList; - d->m_modelList = 0; + delete d->m_listAccessor; + d->m_listAccessor = 0; d->m_modelVariant = model; if (d->m_listModelInterface) { // Assume caller has released all items. @@ -642,8 +642,8 @@ void QFxVisualDataModel::setModel(const QVariant &model) this, SLOT(_q_destroyingPackage(QmlPackage*))); return; } - d->m_modelList = new QmlListAccessor; - d->m_modelList->setList(model, d->m_context?d->m_context->engine():qmlEngine(this)); + d->m_listAccessor = new QmlListAccessor; + d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this)); if (d->m_delegate && d->modelCount()) { emit itemsInserted(0, d->modelCount()); emit countChanged(); diff --git a/src/declarative/util/qmltimer.cpp b/src/declarative/util/qmltimer.cpp index b95d6ad..fdc57ff 100644 --- a/src/declarative/util/qmltimer.cpp +++ b/src/declarative/util/qmltimer.cpp @@ -100,6 +100,8 @@ QmlTimer::QmlTimer(QObject *parent) \qmlproperty int Timer::interval Sets the \a interval in milliseconds between triggering. + + The default interval is 1000 milliseconds. */ void QmlTimer::setInterval(int interval) { @@ -123,6 +125,8 @@ int QmlTimer::interval() const For a non-repeating timer, \a running will be set to false after the timer has been triggered. + \a running defaults to false. + \sa repeat */ bool QmlTimer::isRunning() const @@ -148,6 +152,8 @@ void QmlTimer::setRunning(bool running) specified interval; otherwise, the timer will trigger once at the specified interval and then stop (i.e. running will be set to false). + \a repeat defaults to false. + \sa running */ bool QmlTimer::isRepeating() const @@ -169,7 +175,11 @@ void QmlTimer::setRepeating(bool repeating) \qmlproperty bool Timer::triggeredOnStart If \a triggeredOnStart is true, the timer will be triggered immediately - when started, and subsequently at the specified interval. + when started, and subsequently at the specified interval. Note that for + a Timer with \e repeat set to false, this will result in the timer being + triggered twice; once on start, and again at the interval. + + \a triggeredOnStart defaults to false. \sa running */ @@ -198,7 +208,7 @@ void QmlTimer::setTriggeredOnStart(bool triggeredOnStart) void QmlTimer::start() { Q_D(QmlTimer); - d->pause.start(); + setRunning(true); } /*! @@ -211,7 +221,7 @@ void QmlTimer::start() void QmlTimer::stop() { Q_D(QmlTimer); - d->pause.stop(); + setRunning(false); } void QmlTimer::update() diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index 4724278..f2ddbb7 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -7,13 +7,16 @@ SUBDIRS += datetimeformatter \ pathview \ qfxtext \ qfxtextedit \ - simplecanvasitem \ repeater \ qmllanguage \ qmlecmascript \ qmlmetaproperty \ qmllist \ qmllistaccessor \ + qmltimer \ + qfxloader \ + qfxwebview \ + states \ visual # Tests which should run in Pulse diff --git a/tests/auto/declarative/qmltimer/qmltimer.pro b/tests/auto/declarative/qmltimer/qmltimer.pro new file mode 100644 index 0000000..e7edd96 --- /dev/null +++ b/tests/auto/declarative/qmltimer/qmltimer.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +SOURCES += tst_qmltimer.cpp + +DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/declarative/qmltimer/tst_qmltimer.cpp b/tests/auto/declarative/qmltimer/tst_qmltimer.cpp new file mode 100644 index 0000000..15b558f --- /dev/null +++ b/tests/auto/declarative/qmltimer/tst_qmltimer.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include + +class tst_qmltimer : public QObject +{ + Q_OBJECT +public: + tst_qmltimer(); + +private slots: + void notRepeating(); + void notRepeatingStart(); + void repeat(); + void triggeredOnStart(); + void triggeredOnStartRepeat(); +}; + +class TimerHelper : public QObject +{ + Q_OBJECT +public: + TimerHelper() : QObject(), count(0) + { + } + + int count; + +public slots: + void timeout() { + ++count; + } +}; + +#if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) +// Increase wait as emulator startup can cause unexpected delays +#define TIMEOUT_TIMEOUT 2000 +#else +#define TIMEOUT_TIMEOUT 200 +#endif + +tst_qmltimer::tst_qmltimer() +{ +} + +void tst_qmltimer::notRepeating() +{ + QmlEngine engine; + QmlComponent component(&engine, QByteArray("import Qt 4.6\nTimer { interval: 100; running: true }"), QUrl("file://")); + QmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); +} + +void tst_qmltimer::notRepeatingStart() +{ + QmlEngine engine; + QmlComponent component(&engine, QByteArray("import Qt 4.6\nTimer { interval: 100 }"), QUrl("file://")); + QmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 0); + + timer->start(); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 1); +} + +void tst_qmltimer::repeat() +{ + QmlEngine engine; + QmlComponent component(&engine, QByteArray("import Qt 4.6\nTimer { interval: 100; repeat: true; running: true }"), QUrl("file://")); + QmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QCOMPARE(helper.count, 0); + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > 0); + int oldCount = helper.count; + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > oldCount); +} + +void tst_qmltimer::triggeredOnStart() +{ + QmlEngine engine; + QmlComponent component(&engine, QByteArray("import Qt 4.6\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl("file://")); + QmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QTest::qWait(1); + QCOMPARE(helper.count, 1); + + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 2); + QTest::qWait(TIMEOUT_TIMEOUT); + QCOMPARE(helper.count, 2); +} + +void tst_qmltimer::triggeredOnStartRepeat() +{ + QmlEngine engine; + QmlComponent component(&engine, QByteArray("import Qt 4.6\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl("file://")); + QmlTimer *timer = qobject_cast(component.create()); + QVERIFY(timer != 0); + + TimerHelper helper; + connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout())); + QTest::qWait(1); + QCOMPARE(helper.count, 1); + + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > 1); + int oldCount = helper.count; + QTest::qWait(TIMEOUT_TIMEOUT); + QVERIFY(helper.count > oldCount); +} + +QTEST_MAIN(tst_qmltimer) + +#include "tst_qmltimer.moc" -- cgit v0.12 From e79cf93c8b724c8eac042e68ba8dee0b9f2feee3 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 7 Oct 2009 15:02:04 +1000 Subject: Remove redundant QFxItem::activeFocusChanged(); is not used anywhere, presumedly replaced by QFxItem::focusChanged(). --- doc/src/declarative/focus.qdoc | 6 +++--- doc/src/tutorials/declarative.qdoc | 2 +- examples/examples.pro | 1 - src/declarative/fx/qfxitem.cpp | 16 ---------------- src/declarative/fx/qfxitem.h | 2 -- src/declarative/fx/qfxtextedit.cpp | 2 +- 6 files changed, 5 insertions(+), 24 deletions(-) diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc index 028b5f0..dd5dcaf 100644 --- a/doc/src/declarative/focus.qdoc +++ b/doc/src/declarative/focus.qdoc @@ -35,12 +35,12 @@ Item { \section1 Querying the Active Focus Item Whether or not an \l Item has \e {active focus} can be queried through the -read-only property \c {Item::activeFocus}. For example, here we have a \l Text +read-only property \c {Item::focus}. For example, here we have a \l Text element whose text is determined by whether or not it has \e {active focus}. \code Text { - text: activeFocus ? "I have active focus!" : "I do not have active focus" + text: focus ? "I have active focus!" : "I do not have active focus" } \endcode @@ -167,7 +167,7 @@ Conceptually \e {focus scopes} are quite simple. \o Within each \e {focus scope} one element may have \c {Item::focus} set to true. If more than one \l Item has the \c {Item::focus} property set, the first is selected and the others are unset, just like when there are no \e {focus scopes}. \o When a \e {focus scope} receives \e {active focus}, the contained element with \c {Item::focus} set (if any) also gets \e {active focus}. If this element is also a \l FocusScope, the proxying behaviour continues. Both the -\e {focus scope} and the sub-focused item will have \c {Item::activeFocus} set. +\e {focus scope} and the sub-focused item will have \c {Item::focus} set. \endlist So far the example has the second component statically selected. It is trivial diff --git a/doc/src/tutorials/declarative.qdoc b/doc/src/tutorials/declarative.qdoc index 48beabd..bbc3d15 100644 --- a/doc/src/tutorials/declarative.qdoc +++ b/doc/src/tutorials/declarative.qdoc @@ -500,7 +500,7 @@ to receive focus \endlist - The read-only property activeFocus can be used to determine whether a + The read-only property focus can be used to determine whether a component will receive key input. Any un-handled keys will be passed to the components parent, which in turn will pass keys it doesn't handle up to its own ancestors. diff --git a/examples/examples.pro b/examples/examples.pro index 7acd67b..c53bc7d 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -46,7 +46,6 @@ contains(QT_CONFIG, multimedia) { contains(QT_CONFIG, script): SUBDIRS += script contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon -contains(QT_CONFIG, webkit): SUBDIRS += webkit embedded:SUBDIRS += qws !wince*:!symbian: { !contains(QT_EDITION, Console):contains(QT_BUILD_PARTS, tools):SUBDIRS += designer diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 4d31aaa..6a9af1b 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -1257,12 +1257,6 @@ QFxKeysAttached *QFxKeysAttached::qmlAttachedProperties(QObject *obj) */ /*! - \fn void QFxItem::activeFocusChanged() - - This signal is emitted when this item gains active focus. -*/ - -/*! \fn void QFxItem::baselineOffsetChanged() This signal is emitted when the baseline offset of the item @@ -2260,16 +2254,6 @@ void QFxItem::setKeepMouseGrab(bool keep) } /*! - This function emits the \e activeFocusChanged signal. - \a flag is not used. - */ -void QFxItem::activeFocusChanged(bool flag) -{ - Q_UNUSED(flag); - emit activeFocusChanged(); -} - -/*! This function emits the \e focusChanged signal. Subclasses overriding this function should call up diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 30c522f..674940d 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -166,7 +166,6 @@ Q_SIGNALS: void stateChanged(const QString &); void focusChanged(); void wantsFocusChanged(); - void activeFocusChanged(); void parentChanged(); protected: @@ -183,7 +182,6 @@ protected: virtual void classBegin(); virtual void componentComplete(); virtual void focusChanged(bool); - virtual void activeFocusChanged(bool); virtual void keyPressEvent(QKeyEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); virtual void inputMethodEvent(QInputMethodEvent *); diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index f4c2e4c..7eb25a8 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -822,7 +822,7 @@ void QFxTextEdit::keyReleaseEvent(QKeyEvent *event) \overload Handles changing of the focus property. Focus is applied to the control even if the edit does not have active focus. This is because things - like KeyProxy can give the behavior of focus even when activeFocus isn't + like KeyProxy can give the behavior of focus even when hasFocus() isn't true. */ void QFxTextEdit::focusChanged(bool hasFocus) -- cgit v0.12 From 99573a8e81fcea38c5f68b340068fff266315c03 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 15:37:44 +1000 Subject: Make Script an instrinsic type This allows us to delay the QML load until external script files have been loaded from the network, and to correctly scope these scripts. --- src/declarative/qml/qml.pri | 1 + src/declarative/qml/qmlcompiler.cpp | 78 ++++++++- src/declarative/qml/qmlcompiler_p.h | 1 + src/declarative/qml/qmlcompositetypedata_p.h | 22 +++ src/declarative/qml/qmlcompositetypemanager.cpp | 152 ++++++++++++++++- src/declarative/qml/qmlcompositetypemanager_p.h | 6 + src/declarative/qml/qmlcontext.cpp | 39 +++++ src/declarative/qml/qmlcontext_p.h | 1 + src/declarative/qml/qmlinstruction_p.h | 4 + src/declarative/qml/qmlmetaproperty.cpp | 2 +- src/declarative/qml/qmlparser.cpp | 2 + src/declarative/qml/qmlparser_p.h | 5 + src/declarative/qml/qmlscript.cpp | 82 ++++++++++ src/declarative/qml/qmlscriptparser.cpp | 51 +++++- src/declarative/qml/qmlscriptparser_p.h | 2 + src/declarative/qml/qmlvme.cpp | 7 + src/declarative/util/qmlscript.cpp | 209 ------------------------ src/declarative/util/qmlscript.h | 84 ---------- src/declarative/util/util.pri | 2 - 19 files changed, 441 insertions(+), 309 deletions(-) create mode 100644 src/declarative/qml/qmlscript.cpp delete mode 100644 src/declarative/util/qmlscript.cpp delete mode 100644 src/declarative/util/qmlscript.h diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index e46dd3f..a2e2050 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -35,6 +35,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlsqldatabase.cpp \ qml/qmetaobjectbuilder.cpp \ qml/qmlwatcher.cpp \ + qml/qmlscript.cpp \ qml/qmlpropertycache.cpp \ qml/qmlintegercache.cpp \ qml/qmltypenamecache.cpp \ diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 4b5c5bf..12e8101 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -669,7 +669,11 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) if (obj->metatype == &QmlComponent::staticMetaObject) { COMPILE_CHECK(buildComponent(obj, ctxt)); return true; - } + } + + // Build any script blocks for this type + for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii) + COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii))); // Object instantiations reset the binding context BindingContext objCtxt(obj); @@ -824,6 +828,15 @@ void QmlCompiler::genObject(QmlParser::Object *obj) output->bytecode << id; } + // Set any script blocks + for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) { + QmlInstruction script; + script.type = QmlInstruction::StoreScript; + script.line = -1; // ### + script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); + output->bytecode << script; + } + // Begin the class if (obj->parserStatusCast != -1) { QmlInstruction begin; @@ -1000,7 +1013,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, // Find, check and set the "id" property (if any) Property *idProp = 0; if (obj->properties.count() > 1 || - (obj->properties.count() == 1 && obj->properties.begin().key() != "id")) + (obj->properties.count() == 1 && obj->properties.begin().key() != "id") || + !obj->scriptBlockObjects.isEmpty()) COMPILE_EXCEPTION(obj, "Invalid component specification"); if (obj->properties.count()) @@ -1037,6 +1051,66 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, return true; } +bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) +{ + QString scriptCode; + + if (script->properties.count() == 1 && + script->properties.begin().key() == QByteArray("source")) { + + Property *source = *script->properties.begin(); + if (script->defaultProperty) + COMPILE_EXCEPTION(source, "Invalid Script block. Specify either the source property or inline script."); + + if (source->value || source->values.count() != 1 || + source->values.at(0)->object || !source->values.at(0)->value.isString()) + COMPILE_EXCEPTION(source, "Invalid Script source value"); + + QString sourceUrl = + output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); + + for (int ii = 0; ii < unit->resources.count(); ++ii) { + if (unit->resources.at(ii)->url == sourceUrl) { + scriptCode = QString::fromUtf8(unit->resources.at(ii)->data); + break; + } + } + + } else if (!script->properties.isEmpty()) { + COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); + } else if (script->defaultProperty) { + QmlParser::Location currentLocation; + + for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) { + Value *v = script->defaultProperty->values.at(ii); + if (v->object || !v->value.isString()) + COMPILE_EXCEPTION(v, "Invalid Script block"); + + if (ii == 0) { + currentLocation = v->location.start; + scriptCode.append(QString(currentLocation.column, QLatin1Char(' '))); + } + + while (currentLocation.line < v->location.start.line) { + scriptCode.append(QLatin1String("\n")); + currentLocation.line++; + currentLocation.column = 0; + } + + scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' '))); + + scriptCode += v->value.asString(); + currentLocation = v->location.end; + currentLocation.column++; + } + } + + if (!scriptCode.isEmpty()) + obj->scriptBlocks.append(scriptCode); + + return true; +} + bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj, const BindingContext &ctxt) { diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index fd361fd..1d27342 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -171,6 +171,7 @@ private: bool buildObject(QmlParser::Object *obj, const BindingContext &); + bool buildScript(QmlParser::Object *obj, QmlParser::Object *script); bool buildComponent(QmlParser::Object *obj, const BindingContext &); bool buildSubObject(QmlParser::Object *obj, const BindingContext &); bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj, diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h index 48c6c2b..fa11137 100644 --- a/src/declarative/qml/qmlcompositetypedata_p.h +++ b/src/declarative/qml/qmlcompositetypedata_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE +class QmlCompositeTypeResource; class QmlCompositeTypeData : public QmlRefCount { public: @@ -101,6 +102,7 @@ public: }; QList types; + QList resources; // Add or remove p as a waiter. When the QmlCompositeTypeData becomes // ready, the QmlComponentPrivate::typeDataReady() method will be invoked on @@ -122,5 +124,25 @@ private: QmlCompiledData *compiledComponent; }; +class QmlCompositeTypeResource : public QmlRefCount +{ +public: + QmlCompositeTypeResource(); + virtual ~QmlCompositeTypeResource(); + + enum Status { + Invalid, + Complete, + Error, + Waiting + }; + Status status; + + QList dependants; + + QString url; + QByteArray data; +}; + #endif // QMLCOMPOSITETYPEDATA_P_H diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index a99cff0..71b4ef0 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -63,6 +63,9 @@ QmlCompositeTypeData::~QmlCompositeTypeData() for (int ii = 0; ii < dependants.count(); ++ii) dependants.at(ii)->release(); + for (int ii = 0; ii < resources.count(); ++ii) + resources.at(ii)->release(); + if (compiledComponent) compiledComponent->release(); @@ -70,6 +73,16 @@ QmlCompositeTypeData::~QmlCompositeTypeData() delete component; } +QmlCompositeTypeResource::QmlCompositeTypeResource() +{ +} + +QmlCompositeTypeResource::~QmlCompositeTypeResource() +{ + for (int ii = 0; ii < dependants.count(); ++ii) + dependants.at(ii)->release(); +} + void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p) { waiters << p; @@ -142,6 +155,10 @@ QmlCompositeTypeManager::~QmlCompositeTypeManager() (*iter)->release(); iter = components.erase(iter); } + for (Resources::Iterator iter = resources.begin(); iter != resources.end();) { + (*iter)->release(); + iter = resources.erase(iter); + } } QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url) @@ -181,8 +198,16 @@ void QmlCompositeTypeManager::clearCache() ++iter; } } -} + for (Resources::Iterator iter = resources.begin(); iter != resources.end();) { + if ((*iter)->status != QmlCompositeTypeResource::Waiting) { + (*iter)->release(); + iter = resources.erase(iter); + } else { + ++iter; + } + } +} void QmlCompositeTypeManager::replyFinished() { @@ -215,6 +240,52 @@ void QmlCompositeTypeManager::replyFinished() reply->deleteLater(); } +void QmlCompositeTypeManager::resourceReplyFinished() +{ + QNetworkReply *reply = static_cast(sender()); + + QmlCompositeTypeResource *resource = resources.value(reply->url().toString()); + Q_ASSERT(resource); + + if (reply->error() != QNetworkReply::NoError) { + + resource->status = QmlCompositeTypeResource::Error; + + } else { + + resource->status = QmlCompositeTypeResource::Complete; + resource->data = reply->readAll(); + + } + + doComplete(resource); + reply->deleteLater(); +} + +void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource) +{ + QUrl url(resource->url); + + if (url.scheme() == QLatin1String("file")) { + + QFile file(url.toLocalFile()); + if (file.open(QFile::ReadOnly)) { + resource->data = file.readAll(); + resource->status = QmlCompositeTypeResource::Complete; + } else { + resource->status = QmlCompositeTypeResource::Error; + } + + } else { + + QNetworkReply *reply = + engine->networkAccessManager()->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(finished()), + this, SLOT(resourceReplyFinished())); + + } +} + void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit) { QUrl url(unit->imports.baseUrl()); @@ -308,6 +379,15 @@ void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit) } } +void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource) +{ + for (int ii = 0; ii < resource->dependants.count(); ++ii) { + checkComplete(resource->dependants.at(ii)); + resource->dependants.at(ii)->release(); + } + resource->dependants.clear(); +} + void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit) { if (unit->status != QmlCompositeTypeData::Waiting) @@ -329,12 +409,33 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit) waiting++; } } + for (int ii = 0; ii < unit->resources.count(); ++ii) { + QmlCompositeTypeResource *r = unit->resources.at(ii); + + if (!r) + continue; + + if (r->status == QmlCompositeTypeResource::Error) { + unit->status = QmlCompositeTypeData::Error; + QmlError error; + error.setUrl(unit->imports.baseUrl()); + error.setDescription(QLatin1String("Resource ") + r->url + + QLatin1String(" unavailable")); + unit->errors << error; + doComplete(unit); + return; + } else if (r->status == QmlCompositeTypeData::Waiting) { + waiting++; + } + } + if (!waiting) { unit->status = QmlCompositeTypeData::Complete; doComplete(unit); } } +// ### Check ref counting in here void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) { QList types = unit->data.referencedTypes(); @@ -346,12 +447,6 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) QmlCompositeTypeData::TypeReference ref; - if (typeName == QByteArray("Property") || - typeName == QByteArray("Signal")) { - unit->types << ref; - continue; - } - QUrl url; int majorVersion; int minorVersion; @@ -431,6 +526,49 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) unit->types << ref; } + QList resourceList = unit->data.referencedResources(); + for (int ii = 0; ii < resourceList.count(); ++ii) { + QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii)); + + QmlCompositeTypeResource *resource = resources.value(url.toString()); + + if (!resource) { + resource = new QmlCompositeTypeResource; + resource->status = QmlCompositeTypeResource::Waiting; + resource->url = url.toString(); + resources.insert(resource->url, resource); + + loadResource(resource); + } + + switch(resource->status) { + case QmlCompositeTypeResource::Invalid: + case QmlCompositeTypeResource::Error: + unit->status = QmlCompositeTypeData::Error; + { + QmlError error; + error.setUrl(unit->imports.baseUrl()); + error.setDescription(QLatin1String("Resource ") + resource->url + + QLatin1String(" unavailable")); + unit->errors << error; + } + doComplete(unit); + return; + + case QmlCompositeTypeData::Complete: + break; + + case QmlCompositeTypeData::Waiting: + unit->addref(); + resource->dependants << unit; + waiting++; + break; + } + + resource->addref(); + unit->resources << resource; + } + if (waiting) { unit->status = QmlCompositeTypeData::Waiting; } else { diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h index 8f16998..843a9cf 100644 --- a/src/declarative/qml/qmlcompositetypemanager_p.h +++ b/src/declarative/qml/qmlcompositetypemanager_p.h @@ -67,6 +67,7 @@ class QmlComponent; class QmlDomDocument; class QmlCompositeTypeData; +class QmlCompositeTypeResource; class QmlCompositeTypeManager : public QObject { @@ -88,19 +89,24 @@ public: private Q_SLOTS: void replyFinished(); + void resourceReplyFinished(); void requestProgress(qint64 received, qint64 total); private: void loadSource(QmlCompositeTypeData *); + void loadResource(QmlCompositeTypeResource *); void compile(QmlCompositeTypeData *); void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &); void doComplete(QmlCompositeTypeData *); + void doComplete(QmlCompositeTypeResource *); void checkComplete(QmlCompositeTypeData *); QmlEngine *engine; typedef QHash Components; Components components; + typedef QHash Resources; + Resources resources; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index a1eb5de..549925f 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -48,6 +48,7 @@ #include #include #include +#include // 6-bits #define MAXIMUM_DEFAULT_OBJECTS 63 @@ -60,6 +61,44 @@ QmlContextPrivate::QmlContextPrivate() { } +void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) +{ + if (!engine) + return; + + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + QScriptContext *scriptContext = scriptEngine->pushCleanContext(); + scriptContext->pushScope(scriptValue); + + if (scopeObject) + scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); + + QScriptValue scope = scriptEngine->newObject(); + scriptContext->setActivationObject(scope); + + QScriptValue val = scriptEngine->evaluate(script); + + if (scriptEngine->hasUncaughtException()) { + if (scriptEngine->uncaughtException().isError()){ + QScriptValue exception = scriptEngine->uncaughtException(); + if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ + qWarning() << exception.property(QLatin1String("fileName")).toString() + << scriptEngine->uncaughtExceptionLineNumber() + << exception.toString(); + + } else { + qmlInfo(scopeObject) << exception.toString(); + } + } + } + + scriptEngine->popContext(); + + scripts.append(scope); +} + void QmlContextPrivate::dump() { dump(0); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 22e5895..d18bfda 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -94,6 +94,7 @@ public: QScriptValue scriptValue; QList scripts; + void addScript(const QString &script, QObject *scope); QUrl url; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 38b3191..1dcdace 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -118,6 +118,7 @@ public: StoreInterface, /* storeObject */ StoreSignal, /* storeSignal */ + StoreScript, /* storeScript */ // // Unresolved single assignment @@ -238,6 +239,9 @@ public: int value; } storeString; struct { + int value; + } storeScript; + struct { int propertyIndex; int value; } storeUrl; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 155b34a..302ce8c 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -564,7 +564,7 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const if (!isProperty() || (type() & Attached) || !d->object) return 0; - d->setBinding(d->object, d->core, newBinding); + return d->setBinding(d->object, d->core, newBinding); } QmlAbstractBinding * diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 39fe1e2..8c46939 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -82,6 +82,8 @@ QmlParser::Object::~Object() prop->release(); foreach(const DynamicProperty &prop, dynamicProperties) if (prop.defaultValue) prop.defaultValue->release(); + foreach(Object *obj, scriptBlockObjects) + obj->release(); } void Object::setBindingBit(int b) diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index e0579b0..16862eb 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -151,6 +151,8 @@ namespace QmlParser Property *defaultProperty; QHash properties; + QList scriptBlockObjects; + // Output of the compilation phase (these properties continue to exist // in either the defaultProperty or properties members too) void addValueProperty(Property *); @@ -164,6 +166,9 @@ namespace QmlParser QList groupedProperties; QList valueTypeProperties; + // Script blocks that were nested under this object + QStringList scriptBlocks; + // The bytes to cast instances by to get to the QmlParserStatus // interface. -1 indicates the type doesn't support this interface. // Set by the QmlCompiler. diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp new file mode 100644 index 0000000..307d72f --- /dev/null +++ b/src/declarative/qml/qmlscript.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// This is just a dummy file to include the documentation + +/*! + \qmlclass Script QmlScript + \brief The Script element adds JavaScript snippets. + \ingroup group_utility + + QmlScript is used to add convenient JavaScript "glue" methods to + your Qt Declarative application or component. While you can have any JavaScript code + within a QmlScript, it is best to limit yourself to defining functions. + + \qml + Script { + function debugMyComponent() { + print(text.text); + print(otherinterestingitem.property); + } + } + MouseRegion { onClicked: debugMyComponent() } + \endqml + + \note QmlScript executes JavaScript as soon as it is specified. + When defining a component, this may be before the execution context is + fully specified. As a result some properties or items may not be + accessible. By limiting your JavaScript to defining functions that are + only executed later once the context is fully defined, this problem is + avoided. +*/ + +/*! + \qmlproperty string Script::script + \default + JavaScript code to execute. +*/ + +/*! + \qmlproperty url Script::source + + Setting this property causes the Script element to read JavaScript code from + the file specified. +*/ diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index c126830..1c7bf83 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -289,12 +289,26 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, if (lastTypeDot >= 0) resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/')); - QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); + bool isScript = resolvableObjectType == QLatin1String("Script"); + + if (isScript) { + if (_stateStack.isEmpty() || _stateStack.top().property) { + QmlError error; + error.setDescription(QLatin1String("Invalid use of Script block")); + error.setLine(typeLocation.startLine); + error.setColumn(typeLocation.startColumn); + _parser->_errors << error; + } + } Object *obj = new Object; - obj->type = typeRef->id; - typeRef->refObjects.append(obj); + if (!isScript) { + QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); + obj->type = typeRef->id; + + typeRef->refObjects.append(obj); + } // XXX this doesn't do anything (_scope never builds up) _scope.append(resolvableObjectType); @@ -303,7 +317,11 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, obj->location = location; - if (propertyCount) { + if (isScript) { + + _stateStack.top().object->scriptBlockObjects.append(obj); + + } else if (propertyCount) { Property *prop = currentProperty(); Value *v = new Value; @@ -385,6 +403,26 @@ Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId, _stateStack.pop(); // object return obj; + } else if (objectType == QLatin1String("Script")) { + + AST::UiObjectMemberList *it = initializer->members; + for (; it; it = it->next) { + AST::UiScriptBinding *scriptBinding = AST::cast(it->member); + if (! scriptBinding) + continue; + + QString propertyName = asString(scriptBinding->qualifiedId); + if (propertyName == QLatin1String("source")) { + if (AST::ExpressionStatement *stmt = AST::cast(scriptBinding->statement)) { + AST::StringLiteral *string = AST::cast(stmt->expression); + if (string) { + // We need to add this as a resource + _parser->_refUrls << QUrl(string->value->asString()); + } + } + } + } + } return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer); @@ -867,6 +905,11 @@ QList QmlScriptParser::referencedTypes() const return _refTypes; } +QList QmlScriptParser::referencedResources() const +{ + return _refUrls; +} + Object *QmlScriptParser::tree() const { return root; diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h index d489610..b25d6bf 100644 --- a/src/declarative/qml/qmlscriptparser_p.h +++ b/src/declarative/qml/qmlscriptparser_p.h @@ -102,6 +102,7 @@ public: bool parse(const QByteArray &data, const QUrl &url = QUrl()); QList referencedTypes() const; + QList referencedResources() const; QmlParser::Object *tree() const; QList imports() const; @@ -123,6 +124,7 @@ public: QmlParser::Object *root; QList _imports; QList _refTypes; + QList _refUrls; QString _scriptFile; QmlScriptParserJsASTData *data; }; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index 4ba412b..e4eef64 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -564,6 +564,13 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, } break; + case QmlInstruction::StoreScript: + { + QObject *target = stack.top(); + cp->addScript(primitives.at(instr.storeScript.value), target); + } + break; + case QmlInstruction::BeginObject: { QObject *target = stack.top(); diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp deleted file mode 100644 index 5d58f64..0000000 --- a/src/declarative/util/qmlscript.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qmlscript.h" -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QmlScriptPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QmlScript); - -public: - QmlScriptPrivate() : reply(0) {} - - void addScriptToEngine(const QString &, const QString &source=QString()); - - QString script; - QNetworkReply *reply; - QUrl url; -}; - -/*! - \qmlclass Script QmlScript - \brief The Script element adds JavaScript snippets. - \ingroup group_utility - - QmlScript is used to add convenient JavaScript "glue" methods to - your Qt Declarative application or component. While you can have any JavaScript code - within a QmlScript, it is best to limit yourself to defining functions. - - \qml - Script { - function debugMyComponent() { - print(text.text); - print(otherinterestingitem.property); - } - } - MouseRegion { onClicked: debugMyComponent() } - \endqml - - \note QmlScript executes JavaScript as soon as it is specified. - When defining a component, this may be before the execution context is - fully specified. As a result some properties or items may not be - accessible. By limiting your JavaScript to defining functions that are - only executed later once the context is fully defined, this problem is - avoided. -*/ - -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Script,QmlScript) -QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent) -{ -} - -/*! - \qmlproperty string Script::script - \default - JavaScript code to execute. -*/ -QString QmlScript::script() const -{ - Q_D(const QmlScript); - return d->script; -} - -void QmlScript::setScript(const QString &script) -{ - Q_D(QmlScript); - d->script = script; - d->addScriptToEngine(d->script); -} - -/*! - \qmlproperty url Script::source - - Setting this property causes the Script element to read JavaScript code from - the file specified. -*/ -QUrl QmlScript::source() const -{ - Q_D(const QmlScript); - return d->url; -} - -void QmlScript::setSource(const QUrl &source) -{ - Q_D(QmlScript); - if (d->url == source) - return; - d->url = qmlContext(this)->resolvedUrl(source); - -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); - file.open(QIODevice::ReadOnly); - QByteArray ba = file.readAll(); - d->addScriptToEngine(QString::fromUtf8(ba), file.fileName()); - } else -#endif - { - QNetworkRequest req(d->url); - d->reply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->reply, SIGNAL(finished()), - this, SLOT(replyFinished())); - } -} - -void QmlScript::replyFinished() -{ - Q_D(QmlScript); - if (!d->reply->error()) { - QByteArray ba = d->reply->readAll(); - d->addScriptToEngine(QString::fromUtf8(ba), d->url.toString()); - } - d->reply->deleteLater(); - d->reply = 0; -} - -void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &source) -{ -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxPerfTimer pt; -#endif - Q_Q(QmlScript); - QmlEngine *engine = qmlEngine(q); - QmlContext *context = qmlContext(q); - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - - QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(QmlContextPrivate::get(context)->scriptValue); - - QScriptValue scope = scriptEngine->newObject(); - scriptContext->pushScope(scope); - - scriptContext->setActivationObject(scope); - - QScriptValue val = scriptEngine->evaluate(script, source); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ - qWarning() << exception.property(QLatin1String("fileName")).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - - } else { - qmlInfo(q) << exception.toString(); - } - } - } - - scriptEngine->popContext(); - - context->d_func()->scripts.append(scope); -} - -QT_END_NAMESPACE diff --git a/src/declarative/util/qmlscript.h b/src/declarative/util/qmlscript.h deleted file mode 100644 index 4ba4f6b..0000000 --- a/src/declarative/util/qmlscript.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLSCRIPT_H -#define QMLSCRIPT_H - -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QmlScriptPrivate; -class Q_DECLARATIVE_EXPORT QmlScript : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QmlScript) - - Q_PROPERTY(QString script READ script WRITE setScript) - Q_PROPERTY(QUrl source READ source WRITE setSource) - Q_CLASSINFO("DefaultProperty", "script") - -public: - QmlScript(QObject *parent=0); - - QString script() const; - void setScript(const QString &); - - QUrl source() const; - void setSource(const QUrl &); - -private Q_SLOTS: - void replyFinished(); -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QmlScript) - -QT_END_HEADER - -#endif diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index 41c9019..ec9967c 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -4,7 +4,6 @@ SOURCES += \ util/qperformancelog.cpp \ util/qmlconnection.cpp \ util/qmlpackage.cpp \ - util/qmlscript.cpp \ util/qmlanimation.cpp \ util/qmlsystempalette.cpp \ util/qmlspringfollow.cpp \ @@ -29,7 +28,6 @@ HEADERS += \ util/qperformancelog_p.h \ util/qmlconnection.h \ util/qmlpackage.h \ - util/qmlscript.h \ util/qmlanimation.h \ util/qmlanimation_p.h \ util/qmlsystempalette.h \ -- cgit v0.12 From c164ba0b9486e0a559ed4daa076416cd9f81962f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 17:02:55 +1000 Subject: Fix test --- tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index c7f0424..34fa5e9 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -679,7 +679,8 @@ void tst_qmlecmascript::objectToString() MyQmlObject *object = qobject_cast(component.create()); QVERIFY(object != 0); QMetaObject::invokeMethod(object, "testToString"); - QVERIFY(object->stringProperty().startsWith("Qml Object, \"objName\" MyQmlObject_QML_15")); + QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_")); + QVERIFY(object->stringProperty().endsWith(", \"objName\")")); } QTEST_MAIN(tst_qmlecmascript) -- cgit v0.12 From 28e0f484cfb2b677661f0cb1a90a7b88d8f46f03 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Wed, 7 Oct 2009 17:07:55 +1000 Subject: move files to avoid duplication. --- doc/src/declarative/tutorial1.qdoc | 17 ++++---- doc/src/declarative/tutorial2.qdoc | 16 +++---- doc/src/declarative/tutorial3.qdoc | 7 ++- examples/declarative/tutorials/helloworld/Cell.qml | 32 ++++++++++++++ .../tutorials/helloworld/t1/tutorial1.qml | 22 ---------- .../declarative/tutorials/helloworld/t2/Cell.qml | 32 -------------- .../tutorials/helloworld/t2/tutorial2.qml | 31 ------------- .../declarative/tutorials/helloworld/t3/Cell.qml | 20 --------- .../tutorials/helloworld/t3/tutorial3.qml | 51 ---------------------- .../declarative/tutorials/helloworld/tutorial1.qml | 22 ++++++++++ .../declarative/tutorials/helloworld/tutorial2.qml | 31 +++++++++++++ .../declarative/tutorials/helloworld/tutorial3.qml | 51 ++++++++++++++++++++++ 12 files changed, 156 insertions(+), 176 deletions(-) create mode 100644 examples/declarative/tutorials/helloworld/Cell.qml delete mode 100644 examples/declarative/tutorials/helloworld/t1/tutorial1.qml delete mode 100644 examples/declarative/tutorials/helloworld/t2/Cell.qml delete mode 100644 examples/declarative/tutorials/helloworld/t2/tutorial2.qml delete mode 100644 examples/declarative/tutorials/helloworld/t3/Cell.qml delete mode 100644 examples/declarative/tutorials/helloworld/t3/tutorial3.qml create mode 100644 examples/declarative/tutorials/helloworld/tutorial1.qml create mode 100644 examples/declarative/tutorials/helloworld/tutorial2.qml create mode 100644 examples/declarative/tutorials/helloworld/tutorial3.qml diff --git a/doc/src/declarative/tutorial1.qdoc b/doc/src/declarative/tutorial1.qdoc index f46c59d..c9a1c5a 100644 --- a/doc/src/declarative/tutorial1.qdoc +++ b/doc/src/declarative/tutorial1.qdoc @@ -10,7 +10,7 @@ The picture below is a screenshot of this program. Here is the QML code for the application: -\snippet examples/declarative/tutorials/helloworld/t1/tutorial1.qml 0 +\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 0 \section1 Walkthrough @@ -19,19 +19,20 @@ Here is the QML code for the application: First, we need to import the types that we need for this example. Most QML files will import the built-in QML types (like \l{Rectangle}, \l{Image}, ...) that come with Qt with: -\snippet examples/declarative/tutorials/helloworld/t1/tutorial1.qml 3 +\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 3 \section2 Rectangle element -\snippet examples/declarative/tutorials/helloworld/t1/tutorial1.qml 1 +\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 1 We declare a root element of type \l{Rectangle}. It is one of the basic building blocks you can use to create an application in QML. -We give it an \c{id} to be able to refer to it later. In this case, we call it \e page. We also set the \c width, \c height and \c color properties. +We give it an \c{id} to be able to refer to it later. In this case, we call it \e page. +We also set the \c width, \c height and \c color properties. The \l{Rectangle} element contains many other properties (such as \c x and \c y), but these are left at their default values. \section2 Text element -\snippet examples/declarative/tutorials/helloworld/t1/tutorial1.qml 2 +\snippet examples/declarative/tutorials/helloworld/tutorial1.qml 2 We add a \l Text element as a child of our root element that will display the text 'Hello world!'. @@ -44,13 +45,13 @@ In this case, we specify that our text element should be horizontally centered i \section2 Viewing the example -To view what you have created, run the qmlviewer (located in the \c bin directory) with your filename as the first argument. For example, to run the provided completed Tutorial 1 example from the install location, you would type: +To view what you have created, run the qmlviewer (located in the \c bin directory) with your filename as the first argument. +For example, to run the provided completed Tutorial 1 example from the install location, you would type: \code -bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/t1/tutorial1.qml +bin/qmlviewer $QTDIR/examples/declarative/tutorials/helloworld/tutorial1.qml \endcode [\l tutorial] [Next: \l tutorial2] */ - diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc index 21b5ebd..a076a62 100644 --- a/doc/src/declarative/tutorial2.qdoc +++ b/doc/src/declarative/tutorial2.qdoc @@ -15,36 +15,36 @@ defined in its own QML file (for more details, see \l components). Here is the QML code for \c Cell.qml: -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 0 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 0 \section1 Walkthrough \section2 The Cell Component -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 1 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 1 The root element of our component is an \l Item with the \c id \e container. An \l Item is the most basic visual element in QML and is often used as a container for other elements. -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 4 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 4 We declare a \c color property. This property is accessible from \e outside our component, this allows us to instantiate the cells with different colors. This property is just an alias to an existing property - the color of the rectangle that compose the cell (see \l{Properties}). -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 5 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 5 We want our component to also have a signal that we call \e clicked with a \e color parameter. We will use this signal to change the color of the text in the main QML file later. -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 2 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 2 Our cell component is basically a colored rectangle with the \c id \e rectangle. The \c anchors.fill property is a convenient way to set the size of an element. In this case the rectangle will have the same size as its parent (see \l{anchor-layout}{Anchor-based Layout}). -\snippet examples/declarative/tutorials/helloworld/t2/Cell.qml 3 +\snippet examples/declarative/tutorials/helloworld/Cell.qml 3 In order to change the color of the text when clicking on a cell, we create a \l MouseRegion element with the same size as its parent. @@ -56,11 +56,11 @@ When this signal is triggered we want to emit our own \e clicked signal with the In our main QML file, we use our \c Cell component to create the color picker: -\snippet examples/declarative/tutorials/helloworld/t2/tutorial2.qml 0 +\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 0 We create the color picker by putting 6 cells with different colors in a grid. -\snippet examples/declarative/tutorials/helloworld/t2/tutorial2.qml 1 +\snippet examples/declarative/tutorials/helloworld/tutorial2.qml 1 When the \e clicked signal of our cell is triggered, we want to set the color of the text to the color passed as a parameter. We can react to any signal of our component through a property of the name \e 'onSignalName' (see \l{Signal Handlers}). diff --git a/doc/src/declarative/tutorial3.qdoc b/doc/src/declarative/tutorial3.qdoc index 21b7ae5..d766015 100644 --- a/doc/src/declarative/tutorial3.qdoc +++ b/doc/src/declarative/tutorial3.qdoc @@ -11,11 +11,11 @@ We want our text to move to the bottom of the screen, rotate and become red when Here is the QML code: -\snippet examples/declarative/tutorials/helloworld/t3/tutorial3.qml 0 +\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 0 \section1 Walkthrough -\snippet examples/declarative/tutorials/helloworld/t3/tutorial3.qml 2 +\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 2 First, we create a new \e down state for our text element. This state will be activated when the \l MouseRegion is pressed, and deactivated when it is released. @@ -24,7 +24,7 @@ The \e down state includes a set of property changes from our implicit \e {defau (the items as they were initially defined in the QML). Specifically, we set the \c y property of the text to \c 160, the rotation to \c 180 and the \c color to red. -\snippet examples/declarative/tutorials/helloworld/t3/tutorial3.qml 3 +\snippet examples/declarative/tutorials/helloworld/tutorial3.qml 3 Because we don't want the text to appear at the bottom instantly but rather move smoothly, we add a transition between our two states. @@ -44,4 +44,3 @@ For more details on states and transitions, see \l {states-transitions}{States a [Previous: \l tutorial2] [\l tutorial] */ - diff --git a/examples/declarative/tutorials/helloworld/Cell.qml b/examples/declarative/tutorials/helloworld/Cell.qml new file mode 100644 index 0000000..ab6e565 --- /dev/null +++ b/examples/declarative/tutorials/helloworld/Cell.qml @@ -0,0 +1,32 @@ +//![0] +import Qt 4.6 + +//![1] +Item { + id: container +//![4] + property alias color: rectangle.color +//![4] +//![5] + signal clicked(string color) +//![5] + + width: 40; height: 25 +//![1] + +//![2] + Rectangle { + id: rectangle + border.color: "white" + anchors.fill: parent + } +//![2] + +//![3] + MouseRegion { + anchors.fill: parent + onClicked: container.clicked(container.color) + } +//![3] +} +//![0] diff --git a/examples/declarative/tutorials/helloworld/t1/tutorial1.qml b/examples/declarative/tutorials/helloworld/t1/tutorial1.qml deleted file mode 100644 index 93d3c34..0000000 --- a/examples/declarative/tutorials/helloworld/t1/tutorial1.qml +++ /dev/null @@ -1,22 +0,0 @@ -//![0] -//![3] -import Qt 4.6 -//![3] - -//![1] -Rectangle { - id: page - width: 500; height: 200 - color: "lightgray" -//![1] - -//![2] - Text { - id: helloText - text: "Hello world!" - font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter - } -//![2] -} -//![0] diff --git a/examples/declarative/tutorials/helloworld/t2/Cell.qml b/examples/declarative/tutorials/helloworld/t2/Cell.qml deleted file mode 100644 index ab6e565..0000000 --- a/examples/declarative/tutorials/helloworld/t2/Cell.qml +++ /dev/null @@ -1,32 +0,0 @@ -//![0] -import Qt 4.6 - -//![1] -Item { - id: container -//![4] - property alias color: rectangle.color -//![4] -//![5] - signal clicked(string color) -//![5] - - width: 40; height: 25 -//![1] - -//![2] - Rectangle { - id: rectangle - border.color: "white" - anchors.fill: parent - } -//![2] - -//![3] - MouseRegion { - anchors.fill: parent - onClicked: container.clicked(container.color) - } -//![3] -} -//![0] diff --git a/examples/declarative/tutorials/helloworld/t2/tutorial2.qml b/examples/declarative/tutorials/helloworld/t2/tutorial2.qml deleted file mode 100644 index 99889d7..0000000 --- a/examples/declarative/tutorials/helloworld/t2/tutorial2.qml +++ /dev/null @@ -1,31 +0,0 @@ -//![0] -import Qt 4.6 - -Rectangle { - id: page - width: 500; height: 200 - color: "lightgray" - - Text { - id: helloText - text: "Hello world!" - font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter - } - - Grid { - id: colorPicker - anchors.bottom: page.bottom - rows: 2; columns: 3; spacing: 3 - -//![1] - Cell { color: "red"; onClicked: helloText.color = color } -//![1] - Cell { color: "green"; onClicked: helloText.color = color } - Cell { color: "blue"; onClicked: helloText.color = color } - Cell { color: "yellow"; onClicked: helloText.color = color } - Cell { color: "steelblue"; onClicked: helloText.color = color } - Cell { color: "black"; onClicked: helloText.color = color } - } -} -//![0] diff --git a/examples/declarative/tutorials/helloworld/t3/Cell.qml b/examples/declarative/tutorials/helloworld/t3/Cell.qml deleted file mode 100644 index 578369d..0000000 --- a/examples/declarative/tutorials/helloworld/t3/Cell.qml +++ /dev/null @@ -1,20 +0,0 @@ -import Qt 4.6 - -Item { - id: container - property alias color: rectangle.color - signal clicked(string color) - - width: 40; height: 25 - - Rectangle { - id: rectangle - border.color: "white" - anchors.fill: parent - } - - MouseRegion { - anchors.fill: parent - onClicked: container.clicked(container.color) - } -} diff --git a/examples/declarative/tutorials/helloworld/t3/tutorial3.qml b/examples/declarative/tutorials/helloworld/t3/tutorial3.qml deleted file mode 100644 index d641eba..0000000 --- a/examples/declarative/tutorials/helloworld/t3/tutorial3.qml +++ /dev/null @@ -1,51 +0,0 @@ -//![0] -import Qt 4.6 - -Rectangle { - id: page - width: 500; height: 200 - color: "lightgray" - - Text { - id: helloText - text: "Hello world!" - font.pointSize: 24; font.bold: true - y: 30; anchors.horizontalCenter: page.horizontalCenter - transformOrigin: "Center" - -//![1] - MouseRegion { id: mouseRegion; anchors.fill: parent } -//![1] - -//![2] - states: State { - name: "down"; when: mouseRegion.pressed == true - PropertyChanges { target: helloText; y: 160; rotation: 180; color: "red" } - } -//![2] - -//![3] - transitions: Transition { - from: ""; to: "down"; reversible: true - ParallelAnimation { - NumberAnimation { properties: "y,rotation"; duration: 500; easing: "easeInOutQuad" } - ColorAnimation { property: "color"; duration: 500 } - } - } -//![3] - } - - Grid { - id: colorPicker - anchors.bottom: page.bottom - rows: 2; columns: 3; spacing: 3 - - Cell { color: "red"; onClicked: helloText.color = color } - Cell { color: "green"; onClicked: helloText.color = color } - Cell { color: "blue"; onClicked: helloText.color = color } - Cell { color: "yellow"; onClicked: helloText.color = color } - Cell { color: "steelblue"; onClicked: helloText.color = color } - Cell { color: "black"; onClicked: helloText.color = color } - } -} -//![0] diff --git a/examples/declarative/tutorials/helloworld/tutorial1.qml b/examples/declarative/tutorials/helloworld/tutorial1.qml new file mode 100644 index 0000000..93d3c34 --- /dev/null +++ b/examples/declarative/tutorials/helloworld/tutorial1.qml @@ -0,0 +1,22 @@ +//![0] +//![3] +import Qt 4.6 +//![3] + +//![1] +Rectangle { + id: page + width: 500; height: 200 + color: "lightgray" +//![1] + +//![2] + Text { + id: helloText + text: "Hello world!" + font.pointSize: 24; font.bold: true + y: 30; anchors.horizontalCenter: page.horizontalCenter + } +//![2] +} +//![0] diff --git a/examples/declarative/tutorials/helloworld/tutorial2.qml b/examples/declarative/tutorials/helloworld/tutorial2.qml new file mode 100644 index 0000000..99889d7 --- /dev/null +++ b/examples/declarative/tutorials/helloworld/tutorial2.qml @@ -0,0 +1,31 @@ +//![0] +import Qt 4.6 + +Rectangle { + id: page + width: 500; height: 200 + color: "lightgray" + + Text { + id: helloText + text: "Hello world!" + font.pointSize: 24; font.bold: true + y: 30; anchors.horizontalCenter: page.horizontalCenter + } + + Grid { + id: colorPicker + anchors.bottom: page.bottom + rows: 2; columns: 3; spacing: 3 + +//![1] + Cell { color: "red"; onClicked: helloText.color = color } +//![1] + Cell { color: "green"; onClicked: helloText.color = color } + Cell { color: "blue"; onClicked: helloText.color = color } + Cell { color: "yellow"; onClicked: helloText.color = color } + Cell { color: "steelblue"; onClicked: helloText.color = color } + Cell { color: "black"; onClicked: helloText.color = color } + } +} +//![0] diff --git a/examples/declarative/tutorials/helloworld/tutorial3.qml b/examples/declarative/tutorials/helloworld/tutorial3.qml new file mode 100644 index 0000000..d641eba --- /dev/null +++ b/examples/declarative/tutorials/helloworld/tutorial3.qml @@ -0,0 +1,51 @@ +//![0] +import Qt 4.6 + +Rectangle { + id: page + width: 500; height: 200 + color: "lightgray" + + Text { + id: helloText + text: "Hello world!" + font.pointSize: 24; font.bold: true + y: 30; anchors.horizontalCenter: page.horizontalCenter + transformOrigin: "Center" + +//![1] + MouseRegion { id: mouseRegion; anchors.fill: parent } +//![1] + +//![2] + states: State { + name: "down"; when: mouseRegion.pressed == true + PropertyChanges { target: helloText; y: 160; rotation: 180; color: "red" } + } +//![2] + +//![3] + transitions: Transition { + from: ""; to: "down"; reversible: true + ParallelAnimation { + NumberAnimation { properties: "y,rotation"; duration: 500; easing: "easeInOutQuad" } + ColorAnimation { property: "color"; duration: 500 } + } + } +//![3] + } + + Grid { + id: colorPicker + anchors.bottom: page.bottom + rows: 2; columns: 3; spacing: 3 + + Cell { color: "red"; onClicked: helloText.color = color } + Cell { color: "green"; onClicked: helloText.color = color } + Cell { color: "blue"; onClicked: helloText.color = color } + Cell { color: "yellow"; onClicked: helloText.color = color } + Cell { color: "steelblue"; onClicked: helloText.color = color } + Cell { color: "black"; onClicked: helloText.color = color } + } +} +//![0] -- cgit v0.12 From 26fc680ab4344d1c14756459ab92c0413aebf99c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 17:43:07 +1000 Subject: Add Object.destroy(int delay) parameter --- src/declarative/qml/qmlobjectscriptclass.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 2d69590..ce74aef 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -46,6 +46,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -290,9 +291,10 @@ QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngin int delay = 0; if(context->argumentCount() > 0) delay = context->argument(0).toInt32(); - obj->deleteLater(); - //### Should this be delayed as well? - context->thisObject().setData(QScriptValue(engine, 0)); + if (delay > 0) + QTimer::singleShot(delay, obj, SLOT(deleteLater())); + else + obj->deleteLater(); } return engine->nullValue(); } -- cgit v0.12 From 68573410fb50d95a6ce27cd001d2e140b0b4aedd Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Wed, 7 Oct 2009 17:56:09 +1000 Subject: doc cleanup --- doc/src/declarative/anchor-layout.qdoc | 24 ++-- doc/src/declarative/animation.qdoc | 8 +- doc/src/declarative/basictypes.qdoc | 6 +- doc/src/declarative/binding.qdoc | 10 +- doc/src/declarative/extending.qdoc | 252 ++++++++++++++++----------------- doc/src/declarative/focus.qdoc | 38 ++--- doc/src/declarative/qmlforcpp.qdoc | 218 ++++++++++++++-------------- doc/src/declarative/qmlformat.qdoc | 76 +++++----- doc/src/declarative/qmlintro.qdoc | 12 +- 9 files changed, 322 insertions(+), 322 deletions(-) diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc index f3c0f4a..e723d5c 100644 --- a/doc/src/declarative/anchor-layout.qdoc +++ b/doc/src/declarative/anchor-layout.qdoc @@ -10,11 +10,11 @@ In addition to the more traditional \l Grid, \l Row, and \l Column, QML also pro The QML anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write: \code -Rectangle { id: Rect1; ... } -Rectangle { id: Rect2; anchors.left: Rect1.right; ... } +Rectangle { id: rect1; ... } +Rectangle { id: rect2; anchors.left: rect1.right; ... } \endcode -In this case, the left edge of \e Rect2 is bound to the right edge of Rect1, producing the following: +In this case, the left edge of \e rect2 is bound to the right edge of rect1, producing the following: \image edge1.png @@ -25,19 +25,19 @@ The anchoring system also allows you to specify margins and offsets. Margins spe The following example specifies a left margin: \code -Rectangle { id: Rect1; ... } -Rectangle { id: Rect2; anchors.left: Rect1.right; anchors.leftMargin: 5; ... } +Rectangle { id: rect1; ... } +Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... } \endcode -In this case, a margin of 5 pixels is reserved to the left of \e Rect2, producing the following: +In this case, a margin of 5 pixels is reserved to the left of \e rect2, producing the following: \image edge2.png You can specify multiple anchors. For example: \code -Rectangle { id: Rect1; ... } -Rectangle { id: Rect2; anchors.left: Rect1.right; anchors.top: Rect1.bottom; ... } +Rectangle { id: rect1; ... } +Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... } \endcode \image edge3.png @@ -45,8 +45,8 @@ Rectangle { id: Rect2; anchors.left: Rect1.right; anchors.top: Rect1.bottom; ... By specifying multiple horizontal or vertical anchors you can control the size of an item. For example: \code -Rectangle { id: Rect1; x: 0; ... } -Rectangle { id: Rect2; anchors.left: Rect1.right; anchors.right: Rect3.left; ... } +Rectangle { id: rect1; x: 0; ... } +Rectangle { id: rect2; anchors.left: rect1.right; anchors.right: Rect3.left; ... } Rectangle { id: Rect3; x: 150; ... } \endcode @@ -59,11 +59,11 @@ For performance reasons, you can only anchor an item to its siblings and direct \badcode Item { id: Group1 - Rectangle { id: Rect1; ... } + Rectangle { id: rect1; ... } } Item { id: Group2 - Rectangle { id: Rect2; anchors.left: Rect1.right; ... } // invalid anchor! + Rectangle { id: rect2; anchors.left: rect1.right; ... } // invalid anchor! } \endcode diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc index 9554ad5..21263c1 100644 --- a/doc/src/declarative/animation.qdoc +++ b/doc/src/declarative/animation.qdoc @@ -1,10 +1,10 @@ -/*! +/*! \page qmlanimation.html \target qmlanimation \title QML Animation -QML supports three different forms of animation - basic property animation, -states and transitions and property behaviors. +QML supports three different forms of animation - basic property animation, +states and transitions and property behaviors. \section1 Property Animation @@ -122,7 +122,7 @@ QML transitions can use selectors to determine which state changes a transition \code Transition { from: "*" - to: "Details" + to: "details" ... } \endcode diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index ae942fc..6feb91b 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -184,9 +184,9 @@ \qml Item { children: [ - Item { id: Child1 }, - Rectangle { id: Child2 }, - Text { id: Child3 } + Item { id: child1 }, + Rectangle { id: child2 }, + Text { id: child3 } ] } \endqml diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc index e6835ee..99f2853 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/binding.qdoc @@ -5,17 +5,17 @@ Data binding provides a declarative way of specifying the data associated with objects, as well as the relationship between data of different objects. For example, you could bind the text of a label to the value of a slider: as the value of the slider changed, the label would be automatically updated with the new value. -Bindings are created in QML when an expression is assigned to a property. For example, the following produces two rectangles of equal size (\c Rect2 is bound to the size of \c Rect1): +Bindings are created in QML when an expression is assigned to a property. For example, the following produces two rectangles of equal size (\c rect2 is bound to the size of \c rect1): \code -Rectangle { id: Rect1; width: 100; height: 100 } -Rectangle { id: Rect2; width: Rect1.width; height: Rect1.height } +Rectangle { id: rect1; width: 100; height: 100 } +Rectangle { id: rect2; width: rect1.width; height: rect1.height } \endcode There is also a special \l Binding element, which is typically used to bind from the UI to the underlying UI model (see \l {Passing Data Between C++ and QML} for an example of this). The bindings above could be expressed using the \l Binding element as: \code -Binding { target: Rect2; property: "width"; value: Rect1.width } -Binding { target: Rect2; property: "height"; value: Rect1.height } +Binding { target: rect2; property: "width"; value: rect1.width } +Binding { target: rect2; property: "height"; value: rect1.height } \endcode In addition to binding directly to a property, you can also bind to the results of expressions involving properties. For example: diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 2d0dc34..649eab1 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -43,8 +43,8 @@ \page qml-extending.html \title Extending QML -The QML syntax declaratively describes how to construct an in memory object -tree. In Qt, QML is mainly used to describe a visual scene graph, but it is +The QML syntax declaratively describes how to construct an in memory object +tree. In Qt, QML is mainly used to describe a visual scene graph, but it is not conceptually limited to this: the QML format is an abstract description of any object tree. All the QML element types included in Qt are implemented using the C++ extension mechanisms describe on this page. Programmers can use these @@ -57,14 +57,14 @@ QML for their own independent use. \snippet examples/declarative/extending/adding/example.qml 0 -The QML snippet shown above instantiates one \c Person instance and sets +The QML snippet shown above instantiates one \c Person instance and sets the name and shoeSize properties on it. Everything in QML ultimately comes down -to either instantiating an object instance, or assigning a property a value. +to either instantiating an object instance, or assigning a property a value. QML relies heavily on Qt's meta object system and can only instantiate classes that derive from QObject. -The QML engine has no intrinsic knowledge of any class types. Instead the -programmer must define the C++ types, and their corresponding QML name. +The QML engine has no intrinsic knowledge of any class types. Instead the +programmer must define the C++ types, and their corresponding QML name. Custom C++ types are made available to QML using these two macros: @@ -79,11 +79,11 @@ under the name \a QmlName in library URI version VMAJ.VFROM to VMAJ.VTO. \a T and \a QmlName may be the same. Generally the QML_DECLARE_TYPE() macro should be included immediately following -the type declaration (usually in its header file), and the QML_DEFINE_TYPE() +the type declaration (usually in its header file), and the QML_DEFINE_TYPE() macro in the implementation file. QML_DEFINE_TYPE() must not be present in a header file. -Type \a T must be a concrete type that inherits QObject and has a default +Type \a T must be a concrete type that inherits QObject and has a default constructor. \endquotation @@ -106,7 +106,7 @@ of these types: \endlist QML is typesafe. Attempting to assign an invalid value to a property will -generate an error. For example, assuming the name property of the \c Person +generate an error. For example, assuming the name property of the \c Person element had a type of QString, this would cause an error: \code @@ -127,13 +127,13 @@ The QML snippet shown above assigns a \c Person object to the \c BirthdayParty's celebrant property, and assigns three \c Person objects to the guests property. QML can set properties of types that are more complex than basic intrinsics like -integers and strings. Properties can also be object pointers, Qt interface -pointers, lists of object points, and lists of Qt interface pointers. As QML -is typesafe it ensures that only valid types are assigned to these properties, +integers and strings. Properties can also be object pointers, Qt interface +pointers, lists of object points, and lists of Qt interface pointers. As QML +is typesafe it ensures that only valid types are assigned to these properties, just like it does for primitive types. Properties that are pointers to objects or Qt interfaces are declared with the -Q_PROPERTY() macro, just like other properties. The celebrant property +Q_PROPERTY() macro, just like other properties. The celebrant property declaration looks like this: \snippet examples/declarative/extending/properties/birthdayparty.h 1 @@ -143,7 +143,7 @@ property can be assigned. QML also supports assigning Qt interfaces. To assign to a property whose type is a Qt interface pointer, the interface must also be registered with QML. As -they cannot be instantiated directly, registering a Qt interface is different +they cannot be instantiated directly, registering a Qt interface is different from registering a new QML type. The following macros are used instead: \quotation @@ -154,8 +154,8 @@ from registering a new QML type. The following macros are used instead: Register the C++ interface \a T with the QML system. -Generally the QML_DECLARE_INTERFACE() macro should be included immediately -following the interface declaration (usually in its header file), and the +Generally the QML_DECLARE_INTERFACE() macro should be included immediately +following the interface declaration (usually in its header file), and the QML_DEFINE_INTERFACE() macro in an implementation file. QML_DEFINE_INTERFACE() must not be present in a header file. @@ -163,7 +163,7 @@ Following registration, QML can coerce objects that implement this interface for assignment to appropriately typed properties. \endquotation -The guests property is a list of \c Person objects. Properties that are lists +The guests property is a list of \c Person objects. Properties that are lists of objects or Qt interfaces are also declared with the Q_PROPERTY() macro, just like other properties. List properties must have the type \c {QmlList*}. As with object properties, the type \a T must be registered with QML. @@ -172,7 +172,7 @@ The guest property declaration looks like this: \snippet examples/declarative/extending/properties/birthdayparty.h 2 -\l {Extending QML - Object and List Property Types Example} shows the complete +\l {Extending QML - Object and List Property Types Example} shows the complete code used to create the \c BirthdayParty type. \section1 Inheritance and Coercion @@ -182,17 +182,17 @@ code used to create the \c BirthdayParty type. The QML snippet shown above assigns a \c Boy object to the \c BirthdayParty's celebrant property, and assigns three other objects to the guests property. -QML supports C++ inheritance heirarchies and can freely coerce between known, +QML supports C++ inheritance heirarchies and can freely coerce between known, valid object types. This enables the creation of common base classes that allow the assignment of specialized classes to object or list properties. In the snippet shown, both the celebrant and the guests properties retain the Person -type used in the previous section, but the assignment is valid as both the Boy +type used in the previous section, but the assignment is valid as both the Boy and Girl objects inherit from Person. To assign to a property, the property's type must have been registered with QML. Both the QML_DEFINE_TYPE() and QML_DEFINE_INTERFACE() macros already shown can be used to register a type with QML. Additionally, if a type that acts purely -as a base class that cannot be instantiated from QML needs to be +as a base class that cannot be instantiated from QML needs to be registered these macros can be used: \quotation @@ -201,14 +201,14 @@ registered these macros can be used: #define QML_DEFINE_NOCREATE_TYPE(T) \endcode -Register the C++ type \a T with the QML system. QML_DEFINE_NOCREATE_TYPE() +Register the C++ type \a T with the QML system. QML_DEFINE_NOCREATE_TYPE() differs from QML_DEFINE_TYPE() in that it does not define a mapping between the C++ class and a QML element name, so the type is not instantiable from QML, but it is available for type coercion. Generally the QML_DECLARE_TYPE() macro should be included immediately following -the type declaration (usually in its header file), and the -QML_DEFINE_NOCREATE_TYPE() macro in the implementation file. +the type declaration (usually in its header file), and the +QML_DEFINE_NOCREATE_TYPE() macro in the implementation file. QML_DEFINE_NOCREATE_TYPE() must not be present in a header file. Type \a T must inherit QObject, but there are no restrictions on whether it is @@ -216,25 +216,25 @@ concrete or the signature of its constructor. \endquotation QML will automatically coerce C++ types when assigning to either an object -property, or to a list property. Only if coercion fails does an assignment +property, or to a list property. Only if coercion fails does an assignment error occur. -\l {Extending QML - Inheritance and Coercion Example} shows the complete +\l {Extending QML - Inheritance and Coercion Example} shows the complete code used to create the \c Boy and \c Girl types. \section1 Default Property \snippet examples/declarative/extending/default/example.qml 0 -The QML snippet shown above assigns a collection of objects to the +The QML snippet shown above assigns a collection of objects to the \c BirthdayParty's default property. The default property is a syntactic convenience that allows a type designer to -specify a single property as the type's default. The default property is +specify a single property as the type's default. The default property is assigned to whenever no explicit property is specified. As a convenience, it is behaviorally identical to assigning the default property explicitly by name. -From C++, type designers mark the default property using a Q_CLASSINFO() +From C++, type designers mark the default property using a Q_CLASSINFO() annotation: \quotation @@ -245,7 +245,7 @@ Q_CLASSINFO("DefaultProperty", "property") Mark \a property as the class's default property. \a property must be either an object property, or a list property. -A default property is optional. A derived class inherits its base class's +A default property is optional. A derived class inherits its base class's default property, but may override it in its own declaration. \a property can refer to a property declared in the class itself, or a property inherited from a base class. @@ -261,9 +261,9 @@ specify a default property. The QML snippet shown above assigns a number properties to the \c Boy object, including four properties using the grouped property syntax. -Grouped properties collect similar properties together into a single named +Grouped properties collect similar properties together into a single named block. Grouped properties can be used to present a nicer API to developers, and -may also simplify the implementation of common property collections across +may also simplify the implementation of common property collections across different types through implementation reuse. A grouped property block is implemented as a read-only object property. The @@ -271,35 +271,35 @@ shoe property shown is declared like this: \snippet examples/declarative/extending/grouped/person.h 1 -The ShoeDescription type declares the properties available to the grouped +The ShoeDescription type declares the properties available to the grouped property block - in this case the size, color, brand and price properties. -Grouped property blocks may declared and accessed be recusively. +Grouped property blocks may declared and accessed be recusively. -\l {Extending QML - Grouped Properties Example} shows the complete code used to +\l {Extending QML - Grouped Properties Example} shows the complete code used to implement the \c shoe property grouping. \section1 Attached Properties \snippet examples/declarative/extending/attached/example.qml 1 -The QML snippet shown above assigns the rsvp property using the attached +The QML snippet shown above assigns the rsvp property using the attached property syntax. Attached properties allow unrelated types to annotate other types with some -additional properties, generally for their own use. Attached properties are -identified through the use of the attacher type name, in the case shown -\c BirthdayParty, as a suffix to the property name. +additional properties, generally for their own use. Attached properties are +identified through the use of the attacher type name, in the case shown +\c BirthdayParty, as a suffix to the property name. In the example shown, \c BirthdayParty is called the attaching type, and the -Box instance the attachee object instance. +Box instance the attachee object instance. For the attaching type, an attached property block is implemented as a new QObject derived type, called the attachment object. The properties on the -attachment object are those that become available for use as the attached +attachment object are those that become available for use as the attached property block. -Any QML type can become an attaching type by declaring the +Any QML type can become an attaching type by declaring the \c qmlAttachedProperties() public function: \quotation @@ -310,21 +310,21 @@ Return an attachment object, of type \a AttachedPropertiesType, for the attachee \a object instance. It is customary, though not strictly required, for the attachment object to be parented to \a object to prevent memory leaks. -\a AttachedPropertiesType must be a QObject derived type. The properties on +\a AttachedPropertiesType must be a QObject derived type. The properties on this type will be accessible through the attached properties syntax. This method will be called at most once for each attachee object instance. The -QML engine will cache the returned instance pointer for subsequent attached +QML engine will cache the returned instance pointer for subsequent attached property accesses. Consequently the attachment object may not be deleted until \a object is destroyed. \endquotation -Conceptually, attached properties are a \e type exporting a set of additional +Conceptually, attached properties are a \e type exporting a set of additional properties that can be set on \e any other object instance. Attached properties cannot be limited to only attaching to a sub-set of object instances, although their effect may be so limited. -For example, a common usage scenario is for a type to enhance the properties +For example, a common usage scenario is for a type to enhance the properties available to its children in order to gather instance specific data. Here we add a rsvp field to all the guests coming to a birthday party: \code @@ -332,7 +332,7 @@ BirthdayParty { Boy { BirthdayParty.rsvp: "2009-06-01" } } \endcode -However, as a type cannot limit the instances to which the attachment object +However, as a type cannot limit the instances to which the attachment object must attach, the following is also allowed, even though adding a birthday party rsvp in this context will have no effect. \code @@ -349,10 +349,10 @@ an instance can be accessed using the following method: template QObject *qmlAttachedPropertiesObject(QObject *attachee, bool create = true); \endcode -Returns the attachment object attached to \a attachee by the attaching type +Returns the attachment object attached to \a attachee by the attaching type \a T. If type \a T is not a valid attaching type, this method always returns 0. -If \a create is true, a valid attachment object will always be returned, +If \a create is true, a valid attachment object will always be returned, creating it if it does not already exist. If \a create is false, the attachment object will only be returned if it has previously been created. \endquotation @@ -368,8 +368,8 @@ implement the rsvp attached property. The QML snippet shown above associates the evaluation of a ECMAScript expression with the emission of a Qt signal. -All Qt signals on a registered class become available as special "signal -properties" within QML to which the user can assign a single ECMAScript +All Qt signals on a registered class become available as special "signal +properties" within QML to which the user can assign a single ECMAScript expression. The signal property's name is a transformed version of the Qt signal name: "on" is prepended, and the first letter of the signal name upper cased. For example, the signal used in the example above has the following @@ -378,14 +378,14 @@ C++ signature: \snippet examples/declarative/extending/signal/birthdayparty.h 0 In classes with multiple signals with the same name, only the final signal -is accessible as a signal property. Although QML provides an element, +is accessible as a signal property. Although QML provides an element, \l Connection, for accessing the other signals it is less elegant. For the best QML API, class developers should avoid overloading signal names. Signal parameters become accessible by name to the assigned script. An unnamed parameter cannot be accessed, so care should be taken to name all the signal parameters in the C++ class declaration. The intrinsic types -listed in \l {Adding Types}, as well registered object types are permitted as +listed in \l {Adding Types}, as well registered object types are permitted as signal parameter types. Using other types is not an error, but the parameter value will not be accessible from script. @@ -400,14 +400,14 @@ implement the onPartyStarted signal property. The QML snippet shown above assigns a property value to the speaker property. A property value source generates a value for a property that changes over time. -Property value sources are most commonly used to do animation. Rather than +Property value sources are most commonly used to do animation. Rather than constructing an animation object and manually setting the animation's "target" property, a property value source can be assigned directly to a property of any type and automatically set up this association. -The example shown here is rather contrived: the speaker property of the +The example shown here is rather contrived: the speaker property of the BirthdayParty object is a string that is printed every time it is assigned and -the HappyBirthday value source generates the lyrics of the song +the HappyBirthday value source generates the lyrics of the song "Happy Birthday". \snippet examples/declarative/extending/valuesource/birthdayparty.h 0 @@ -417,9 +417,9 @@ the case of a property value source, rather than assigning the object instance itself, the QML engine sets up an association between the value source and the property. -Property value sources are special types that derive from the +Property value sources are special types that derive from the QmlPropertyValueSource base class. This base class contains a single method, -QmlPropertyValueSource::setTarget(), that the QML engine invokes when +QmlPropertyValueSource::setTarget(), that the QML engine invokes when associating the property value source with a property. The relevant part of the HappyBirthday type declaration looks like this: @@ -429,10 +429,10 @@ the HappyBirthday type declaration looks like this: In all other respects, property value sources are regular QML types. They must be registered with the QML engine using the same macros as other types, and can -contain properties, signals and methods just like other types. +contain properties, signals and methods just like other types. When a property value source object is assigned to a property, QML first tries -to assign it normally, as though it were a regular QML type. Only if this +to assign it normally, as though it were a regular QML type. Only if this assignment fails does the engine call the setTarget() method. This allows the type to also be used in contexts other than just as a value source. @@ -444,20 +444,20 @@ implement the HappyBirthday property value source. \snippet examples/declarative/extending/binding/example.qml 0 \snippet examples/declarative/extending/binding/example.qml 1 -The QML snippet shown above uses a property binding to ensure the +The QML snippet shown above uses a property binding to ensure the HappyBirthday's name property remains up to date with the celebrant. Property binding is a core feature of QML. In addition to assigning literal -values, property bindings allow the developer to assign an arbitrarily complex +values, property bindings allow the developer to assign an arbitrarily complex ECMAScript expression that may include dependencies on other property values. -Whenever the expression's result changes - through a change in one of its +Whenever the expression's result changes - through a change in one of its constituent values - the expression is automatically reevaluated and the new result assigned to the property. All properties on custom types automatically support property binding. However, -for binding to work correctly, QML must be able to reliably determine when a +for binding to work correctly, QML must be able to reliably determine when a property has changed so that it knows to reevaluate any bindings that depend on -the property's value. QML relies on the presence of a +the property's value. QML relies on the presence of a \c {Qt's Property System}{NOTIFY signal} for this determination. Here is the celebrant property declaration: @@ -468,7 +468,7 @@ The NOTIFY attribute is followed by a signal name. It is the responsibility of the class implementer to ensure that whenever the property's value changes, the NOTIFY signal is emitted. The signature of the NOTIFY signal is not important to QML. -To prevent loops or excessive evaluation, developers should ensure that the +To prevent loops or excessive evaluation, developers should ensure that the signal is only emitted whenever the property's value is actually changed. If a property, or group of properties, is infrequently used it is permitted to use the same NOTIFY signal for several properties. This should be done with care to @@ -476,10 +476,10 @@ ensure that performance doesn't suffer. To keep QML reliable, if a property does not have a NOTIFY signal, it cannot be used in a binding expression. However, the property can still be assigned -a binding as QML does not need to monitor the property for change in that +a binding as QML does not need to monitor the property for change in that scenario. -Consider a custom type, \c TestElement, that has two properties, "a" and "b". +Consider a custom type, \c TestElement, that has two properties, "a" and "b". Property "a" does not have a NOTIFY signal, and property "b" does have a NOTIFY signal. @@ -495,7 +495,7 @@ TestElement { \endcode The presence of a NOTIFY signal does incur a small overhead. There are cases -where a property's value is set at object construction time, and does not +where a property's value is set at object construction time, and does not subsequently change. The most common case of this is when a type uses \l {Grouped Properties}, and the grouped property object is allocated once, and only freed when the object is deleted. In these cases, the CONSTANT attribute @@ -520,9 +520,9 @@ modifying its source code. When integrating existing classes and technology into QML, their APIs will often need to be tweaked to fit better into the declarative environment. Although -the best results are usually obtained by modifying the original classes -directly, if this is either not possible or is complicated by some other -concerns extension objects allow limited extension possibilities without +the best results are usually obtained by modifying the original classes +directly, if this is either not possible or is complicated by some other +concerns extension objects allow limited extension possibilities without direct modifications. Extension objects can only add properties. @@ -536,29 +536,29 @@ Extension objects can only add properties. \page qml-extending-types.html \title Extending types from QML -Many of the elements available for use in QML are implemented in -\l {QML for C++ Programmers}{C++}. These types are know as "core types". QML -allows programmers to build new, fully functional elements without using C++. -Existing core types can be extended, and new types defined entirely in the QML +Many of the elements available for use in QML are implemented in +\l {QML for C++ Programmers}{C++}. These types are know as "core types". QML +allows programmers to build new, fully functional elements without using C++. +Existing core types can be extended, and new types defined entirely in the QML language. \tableofcontents \section1 Adding new properties -New properties can be added to an existing type. These new properties are +New properties can be added to an existing type. These new properties are available for use within QML, and also appear as regular Qt properties on the C++ object, accessible through the regular property access mechanisms. -Like all properties in QML, custom properties are typed. The type is used to +Like all properties in QML, custom properties are typed. The type is used to define the property's behavior, and also determines the C++ type of the created -Qt property. The following table shows the list of types available when +Qt property. The following table shows the list of types available when declaring a new property, and the corresponding C++ type. \table -\header \o QML Type Name \o C++ Type Name -\row \o int \o int -\row \o bool \o bool +\header \o QML Type Name \o C++ Type Name +\row \o int \o int +\row \o bool \o bool \row \o double \o double \row \o real \o double \row \o string \o QString @@ -589,7 +589,7 @@ in the same type block is an error. However, a new property may reuse the name of an existing property on the type. This should be done with caution, as the existing property will be hidden, and become inaccessible. -The must be one of the QML type names shown in the above table. +The must be one of the QML type names shown in the above table. Additionally, an optional default value of the property can be provided. The default value is a convenient shortcut, but is behaviorally identical to doing it in two steps, like this: @@ -627,10 +627,10 @@ controls the color of the inner rectangle. \section2 Property aliases Property aliases are a more advanced form of property declaration. Unlike a -property definition, that allocates a new, unique storage space for the -property, a property alias connects the newly declared property (called the -aliasing property) to an existing property (the aliased property). Read -operations on the aliasing property act as read operations on the aliased +property definition, that allocates a new, unique storage space for the +property, a property alias connects the newly declared property (called the +aliasing property) to an existing property (the aliased property). Read +operations on the aliasing property act as read operations on the aliased property, and write operations on the aliasing property as write operations on the aliased property. @@ -641,7 +641,7 @@ A property alias declaration looks a lot like a property definition: As the aliasing property has the same type as the aliased property, an explicit type is omitted, and the special "alias" keyword is used. Instead of a default -value, a property alias includes a compulsary alias reference. The alias +value, a property alias includes a compulsary alias reference. The alias reference is used to locate the aliased property. While similar to a property binding, the alias reference syntax is highly restricted. @@ -656,11 +656,11 @@ alias reference syntax may become more flexibly in future releases. Here is the property definition example rewritten to use property aliases. \code Rectangle { - property alias innerColor: InnerRect.color + property alias innerColor: innerRect.color color: "red"; width: 100; height: 100 Rectangle { - id: InnerRect + id: innerRect anchors.centerIn: parent width: parent.width - 10 height: parent.height - 10 @@ -678,24 +678,24 @@ use the aliased property directly. For example, this will not work: \code // Does NOT work - property alias innerColor: InnerRect.color + property alias innerColor: innerRect.color innerColor: "black" \endcode -This behavior is required to allow type developers to redefine the behavior +This behavior is required to allow type developers to redefine the behavior of existing property names while continuing to use the existing behavior within -the type they are building, something that is not possible with property +the type they are building, something that is not possible with property definitions. In the example used so far, this could allows the developer to fix -the external rectangle's color as "red" and redefine the "color" property to +the external rectangle's color as "red" and redefine the "color" property to refer to the inner rectangle, like this: \code Rectangle { - property alias color: InnerRect.color + property alias color: innerRect.color color: "red"; width: 100; height: 100 Rectangle { - id: InnerRect + id: innerRect anchors.centerIn: parent width: parent.width - 10 height: parent.height - 10 @@ -705,18 +705,18 @@ Rectangle { \endcode Users of this type would not be able to affect the color of the red rectangle, -but would find using the "color" property, rather than the strange new +but would find using the "color" property, rather than the strange new "innerColor" property, much more familiar. -A second, much less significant, consequence of the delayed activation of +A second, much less significant, consequence of the delayed activation of aliases is that an alias reference cannot refer to another aliasing property declared within the same component. This will not work: \code // Does NOT work - id: Root - property alias innerColor: InnerRect.color - property alias innerColor2: Root.innerColor + id: root + property alias innerColor: innerRect.color + property alias innerColor2: root.innerColor \endcode From outside the component, aliasing properties appear as regular Qt properties @@ -724,7 +724,7 @@ and consequently can be used in alias references. \section1 Adding new signals -New signals can be added to an existing type. These new signals are available +New signals can be added to an existing type. These new signals are available for use within QML, and also appear as regular Qt signals on the C++ object that can be used in Qt signal/slot connections. @@ -734,9 +734,9 @@ signal [([ [, ...]])] \endcode This declaration may appear anywhere within a type body, but it is customary to -include it at the top. Attempting to declare two signals or methods with the -same name in the same type block is an error. However, a new signal may reuse -the name of an existing signal on the type. This should be done with caution, +include it at the top. Attempting to declare two signals or methods with the +same name in the same type block is an error. However, a new signal may reuse +the name of an existing signal on the type. This should be done with caution, as the existing signal may be hidden and become inaccessible. The options for parameter types are the same as for property types (see @@ -754,7 +754,7 @@ Here are three examples of signal declarations: \section1 Adding new methods -New methods can be added to an existing type. These new methods are available +New methods can be added to an existing type. These new methods are available for use within QML, and also appear as regular Qt slots on the C++ object that can be used in Qt signal/slot connections. @@ -763,9 +763,9 @@ function ([[, ...]]) { } \endcode This declaration may appear anywhere within a type body, but it is customary to -include it at the top. Attempting to declare two methods or signals with the +include it at the top. Attempting to declare two methods or signals with the same name in the same type block is an error. However, a new method may reuse -the name of an existing method on the type. This should be done with caution, +the name of an existing method on the type. This should be done with caution, as the existing method may be hidden and become inaccessible. Methods parameters are not typed. In C++ these parameters are of type QVariant. @@ -783,24 +783,24 @@ Item { \section1 Defining new Components -A component is a reusable type with a well-defined interface built entirely in +A component is a reusable type with a well-defined interface built entirely in QML. Components appear as regular QML elements, and can be used interchangably with core types. Components allow developers to create new types to be reused -in other projects without the use of C++. Components can also help to reduce -duplication inside one project by limiting the need for large numbers of +in other projects without the use of C++. Components can also help to reduce +duplication inside one project by limiting the need for large numbers of copy-and-pasted blocks. -Any snippet of QML code can become a component, just by placing it in the file +Any snippet of QML code can become a component, just by placing it in the file ".qml" where is the new element name, and begins with an uppercase letter. These QML files automatically become available as new QML element types to other QML components and applications in the same directory. -For example, here we show how a component named "Box" is defined and used +For example, here we show how a component named "Box" is defined and used multiple times by an application. \table \row -\o application.qml +\o application.qml \code Rectangle { width: 100; height: 400; @@ -812,19 +812,19 @@ Rectangle { \o Box.qml \code Rectangle { - width: 100; height: 100; + width: 100; height: 100; color: "blue" } \endcode \endtable -Components may be collected into \l {Modules} that gives the +Components may be collected into \l {Modules} that gives the developer more freedom than just putting files in the same directory. \section2 Building reusable components -A component type built to be reused by others must have a well defined -interface. In QML, an interface consists of a defined collection of +A component type built to be reused by others must have a well defined +interface. In QML, an interface consists of a defined collection of properties, signals and methods. Users of a component have access to all the properties, signals and methods defined on the root element of the component. @@ -846,7 +846,7 @@ available externally. Here we add a "text" property: \table \row -\o application.qml +\o application.qml \code Rectangle { width: 100; height: 400; @@ -858,25 +858,25 @@ Rectangle { \o Box.qml \code Rectangle { - property alias text: MyText.text - width: 100; height: 100; + property alias text: myText.text + width: 100; height: 100; color: "blue" Text { - id: MyText + id: myText anchors.centerIn: parent - } + } } \endcode \endtable Methods and signals may be added in the same way. -As all external methods, signals and properties are accessible to external -users, developers should ensure that setting these properties does not have +As all external methods, signals and properties are accessible to external +users, developers should ensure that setting these properties does not have any undesirable side-effects. For most resiliance, root level properties should only be used for literal default values. When a root level property must be used inside the component - such as the children property - property aliases can be used to redirect this property to a "safe" location for external users. -Try to think of the root level properties as being "owned" by the components +Try to think of the root level properties as being "owned" by the components user, rather than the component itself. */ diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc index 028b5f0..1e00bd9 100644 --- a/doc/src/declarative/focus.qdoc +++ b/doc/src/declarative/focus.qdoc @@ -58,12 +58,12 @@ the \c {KeyActions} element has \e {active focus} and pressing the \o \code Rectangle { color: "lightsteelblue"; width: 240; height: 25 - Text { id: MyText } + Text { id: myText } KeyActions { focus: true - keyA: "MyText.text = 'Key A was pressed'" - keyB: "MyText.text = 'Key B was pressed'" - keyC: "MyText.text = 'Key C was pressed'" + keyA: "myText.text = 'Key A was pressed'" + keyB: "myText.text = 'Key B was pressed'" + keyC: "myText.text = 'Key C was pressed'" } } \endcode @@ -92,23 +92,23 @@ Rectangle { color: "red"; width: 240; height: 55 Rectangle { color: "lightsteelblue"; width: 240; height: 25 - Text { id: MyText } + Text { id: myText } KeyActions { focus: true - keyA: "MyText.text = 'Key A was pressed'" - keyB: "MyText.text = 'Key B was pressed'" - keyC: "MyText.text = 'Key C was pressed'" + keyA: "myText.text = 'Key A was pressed'" + keyB: "myText.text = 'Key B was pressed'" + keyC: "myText.text = 'Key C was pressed'" } } Rectangle { y: 30; focus: true color: "lightsteelblue"; width: 240; height: 25 - Text { id: MyText } + Text { id: myText } KeyActions { focus: true - keyA: "MyText.text = 'Key A was pressed'" - keyB: "MyText.text = 'Key B was pressed'" - keyC: "MyText.text = 'Key C was pressed'" + keyA: "myText.text = 'Key A was pressed'" + keyB: "myText.text = 'Key B was pressed'" + keyC: "myText.text = 'Key C was pressed'" } } } @@ -149,12 +149,12 @@ FocusScope { width: 240; height: 25 Rectangle { color: "lightsteelblue"; width: 240; height: 25 - Text { id: MyText } + Text { id: myText } KeyActions { focus: true - keyA: "MyText.text = 'Key A was pressed'" - keyB: "MyText.text = 'Key B was pressed'" - keyC: "MyText.text = 'Key C was pressed'" + keyA: "myText.text = 'Key A was pressed'" + keyB: "myText.text = 'Key B was pressed'" + keyC: "myText.text = 'Key C was pressed'" } } } @@ -186,9 +186,9 @@ Rectangle { \endcode \o \code FocusScope { - id: Page; width: 240; height: 25 + id: page; width: 240; height: 25 MyWidget { focus: true } - MouseRegion { anchors.fill: parent; onClicked: { Page.focus = true } } + MouseRegion { anchors.fill: parent; onClicked: { page.focus = true } } } \endcode \endtable @@ -221,7 +221,7 @@ Rectangle { color: "lightsteelblue"; width: 240; height: 320 ListView { - id: MyView; anchors.fill: parent; focus: true + id: myView; anchors.fill: parent; focus: true model: ListModel { ListElement { name: "Bob" } ListElement { name: "John" } diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc index ab456e5..697ea59 100644 --- a/doc/src/declarative/qmlforcpp.qdoc +++ b/doc/src/declarative/qmlforcpp.qdoc @@ -6,13 +6,13 @@ This page describes the QML format and how to use and extend it from C++. The QML syntax declaratively describes how to construct an in memory - object tree. QML is usually used to describe a visual scene graph - but it is not conceptually limited to this: the QML format is an abstract - description of \bold any object tree. + object tree. QML is usually used to describe a visual scene graph + but it is not conceptually limited to this: the QML format is an abstract + description of \bold any object tree. - QML also includes property bindings. Bindings are ECMAScript expressions - of a properties value. Whenever the value of the expression changes - - either for the first time at startup or subsequently thereafter - the + QML also includes property bindings. Bindings are ECMAScript expressions + of a properties value. Whenever the value of the expression changes - + either for the first time at startup or subsequently thereafter - the property is automatically updated with the new value. \tableofcontents @@ -21,10 +21,10 @@ QmlComponent is used to load a QML file and to create object instances. - In QML a component is the unit of instantiation, and the most basic unit - of scope. A component is like a template for how to construct an object - tree. One component can create multiple instances of this tree, but the - template remains constant. + In QML a component is the unit of instantiation, and the most basic unit + of scope. A component is like a template for how to construct an object + tree. One component can create multiple instances of this tree, but the + template remains constant. The following code uses the C++ interface to create 100 red rectangles based on a simple declarative component description. @@ -37,10 +37,10 @@ // ... do something with the rectangle ... } \endcode - + Each independent file describes a QML component, but it is also possible to create sub-components within a QML file as will be shown later. - + \section1 QML Format 101 This is some sample QML code. @@ -64,8 +64,8 @@ } \endcode - The QML snippet shown above instantiates one \c Image instance and one - \c Text instance and sets properties on both. \bold Everything in QML + The QML snippet shown above instantiates one \c Image instance and one + \c Text instance and sets properties on both. \bold Everything in QML ultimately comes down to either instantiating an object instance, or assigning a property a value. QML relies heavily on Qt's meta object system and can only instantiate classes that derive from QObject. @@ -83,26 +83,26 @@ } \endcode - QML can set properties that are more complex than just simple types like - integers and strings. Properties can be object pointers or Qt interface + QML can set properties that are more complex than just simple types like + integers and strings. Properties can be object pointers or Qt interface pointers or even lists of object or Qt interface pointers! QML is typesafe, and will ensure that only the valid types are assigned to properties. Assigning an object to a property is as simple as assigning a basic - integer. Attempting to assign an object to a property when type coercian + integer. Attempting to assign an object to a property when type coercian fails will produce an error. The following shows an example of valid and of invalid QML and the corresponding C++ classes. \table \row \o - \code + \code class Image : public QObject { - ... + ... Q_PROPERTY(ImageFilter *filter READ filter WRITE setFilter) - }; + }; - class ImageFilter : public QObject + class ImageFilter : public QObject { ... }; @@ -121,11 +121,11 @@ \endtable Classes can also define an optional default property. The default property - is used for assignment if no explicit property has been specified. + is used for assignment if no explicit property has been specified. Any object property can be the default, even complex properties like lists - of objects. The default property of the \c Rect class is the \c children - property, a list of \c Item's. In the following example, as both \c Image - and \c Text inherit from \c Item the \c Image and \c Text instances are + of objects. The default property of the \c Rect class is the \c children + property, a list of \c Item's. In the following example, as both \c Image + and \c Text inherit from \c Item the \c Image and \c Text instances are added to the parent's \c children property. \code @@ -135,10 +135,10 @@ } \endcode - Properties that return read-only object pointers can be used recursively. - This can be used, for example, to group properties together. The + Properties that return read-only object pointers can be used recursively. + This can be used, for example, to group properties together. The \c Text element has a \c font property that returns an object with a number - of sub-properties such as \c family, \c bold, \c italic and \c size. + of sub-properties such as \c family, \c bold, \c italic and \c size. QML makes it easy to interact with these grouped properties, as the following shows - everything you would expect to work, just does. @@ -150,7 +150,7 @@ ... Q_PROPERTY(Font *font READ font); }; - class Font : public QObject + class Font : public QObject { ... Q_PROPERTY(QString family READ family WRITE setFamily); @@ -177,36 +177,36 @@ The QML engine has no intrinsic knowledge of any class types. Instead the programmer must define the C++ types, their corresponding QML name, library namespace, and version availability. - + \code #define QML_DECLARE_TYPE(T) #define QML_DEFINE_TYPE(URI,VMAJ,VFROM,VTO,QmlName,T) \endcode - Adding these macros to your library or executable automatically makes the + Adding these macros to your library or executable automatically makes the C++ type \a T available from the declarative markup language under the name \a QmlName. Of course there's nothing stopping you using the same name for both the C++ and the QML name! - Any type can be added to the QML engine using these macros. The only + Any type can be added to the QML engine using these macros. The only requirements are that \a T inherits QObject, is not abstract, and that it has a default constructor. - \section1 Property Binding + \section1 Property Binding Assigning constant values and trees to properties will only get you so - far. Property binding allows a property's value to be dependant on the + far. Property binding allows a property's value to be dependant on the value of other properties and data. Whenever these dependencies change, - the property's value is automatically updated. + the property's value is automatically updated. - Property bindings are ECMAScript expressions and can be applied to any - object property. C++ classes don't have to do anything special to get + Property bindings are ECMAScript expressions and can be applied to any + object property. C++ classes don't have to do anything special to get binding support other than define appropriate properties. When a non-literal - property assignment appears in a QML file, it is automatically treated as a + property assignment appears in a QML file, it is automatically treated as a property binding. - Here's a simple example that stacks a red, blue and green rectangle. + Here's a simple example that stacks a red, blue and green rectangle. Bindings are used to ensure that the height of each is kept equal to it's - parent's. Were the root rectangle's height property to change, the child + parent's. Were the root rectangle's height property to change, the child rectangles height would be updated automatically. \code @@ -230,25 +230,25 @@ defines how the expression resolves property and variable names. Although the two expressions in the last example are the same, the value of \c parent resolves differently because each executes in a different context. Although - QML generally takes care of everything for the programmer, a thorough + QML generally takes care of everything for the programmer, a thorough understanding of bind contexts is important in some of the more complex QML structures. - Every expression is executed in a bind context, encapsulated by the - QmlContext C++ class. As covered in the class documentation, a - bind context contains a map of names to values, and a list of default + Every expression is executed in a bind context, encapsulated by the + QmlContext C++ class. As covered in the class documentation, a + bind context contains a map of names to values, and a list of default objects. When resolving a name, the name to value map is searched first. - If the name cannot be found, the default object's are iterated in turn and + If the name cannot be found, the default object's are iterated in turn and the context attempts to resolve the name as a property of one of the default objects. There are generally two contexts involved in the execution of a binding. - The first is the "object context" - a bind context associated with the - closest instantiated object and containing just one default object, and + The first is the "object context" - a bind context associated with the + closest instantiated object and containing just one default object, and that's instantiated object itself. The effect of the object - context is pretty simple - names in the binding expression resolve to - properties on the object first. It is important to note - particularly in - the case of grouped properties - the object context is that of the + context is pretty simple - names in the binding expression resolve to + properties on the object first. It is important to note - particularly in + the case of grouped properties - the object context is that of the instantiated object, the consequences of which are shown below. \code @@ -260,7 +260,7 @@ } } \endcode - The second context is the "component context". Each QML component (and + The second context is the "component context". Each QML component (and consequently each QML file) is created in its own unique binding context. Like the object context, the component context contains just one default object - but in this case it is the component's root object. An example @@ -288,7 +288,7 @@ Rectangle { color: "red" width: 100 - Rectangle { + Rectangle { color: "blue" width: 50 height: parent.height @@ -301,13 +301,13 @@ } \endcode - Clearly this sort of fragile relationship is undesirable and unmanageable - - moving the green rectangle to be a sibling of the blue or introducing a + Clearly this sort of fragile relationship is undesirable and unmanageable - + moving the green rectangle to be a sibling of the blue or introducing a further rectangle between the two would break the example. To address this problem, QML includes a way to directly reference any object - within a component (or parent component for that matter), called "ids". - Developers assign an object an id, and can then reference it directly by + within a component (or parent component for that matter), called "ids". + Developers assign an object an id, and can then reference it directly by name. Developers assign an object an id by setting the special \c id property. Every object automatically has this magical property (if the object also has an actual property called \c id, that gets set too). As @@ -316,18 +316,18 @@ \code Rectangle { - id: Root + id: root color: "red" - width: GreenRect.width + 75 - height: Root.height + width: greenRect.width + 75 + height: root.height Rectangle { color: "blue" - width: GreenRect.width + 25 + width: greenRect.width + 25 Rectangle { - id: GreenRect + id: greenRect color: "green" width: 25 - height: Root.height + height: root.height } } } @@ -336,11 +336,11 @@ To relate id's back to QmlContext, id's exist as properties on the component context. - Bind expressions can reference any object property. The QML bind engine - relies on the presence of the NOTIFY signal in the Q_PROPERTY declaration - on a class to alert it that a property's value has changed. If this is + Bind expressions can reference any object property. The QML bind engine + relies on the presence of the NOTIFY signal in the Q_PROPERTY declaration + on a class to alert it that a property's value has changed. If this is omitted, the bind expression can still access the property's value, but - the expression will not be updated if the value changes. The following is + the expression will not be updated if the value changes. The following is an example of a QML friendly property declaration. \code @@ -356,20 +356,20 @@ }; \endcode - While generally no changes are needed to a C++ class to use property + While generally no changes are needed to a C++ class to use property binding, sometimes more advanced interaction between the binding engine and an object is desirable. To facilitate this, there is a special exception in the bind engine for allowing an object to access the binding directly. - If a binding is assigned to a property with a type of QmlBindableValue + If a binding is assigned to a property with a type of QmlBindableValue pointer (ie. QmlBindableValue *), each time the binding value changes, - a QmlBindableValue instance is assigned to that property. The + a QmlBindableValue instance is assigned to that property. The QmlBindableValue instance allows the object to read the binding and to evaluate the binding's current value. \section1 Signal Properties - In addition to reading and writing regular properties, QML allows you to + In addition to reading and writing regular properties, QML allows you to easily associate ECMAScript with signals. Consider the following example, in which Button is a made-up type with a clicked() signal. @@ -385,7 +385,7 @@ Like properties, signals automatically become available in QML without any additional work. As illustrated signals are mapped into QML as special - "signal properties", using the name "on" where the first + "signal properties", using the name "on" where the first character of the signal's name is uppercased. If more than one signal of the same name is exist on a class, only the first is available (see the \l Connection element for more general signal connections). @@ -393,11 +393,11 @@ An important observation to make here is the lack of braces. While both property bindings and signal properties involve executing ECMAScript code, property bindings dynamically update the property value (hence the braces), - whereas with signal properties the constant script "value" is actually - assigned to the signal property. Trying to bind a value to a signal + whereas with signal properties the constant script "value" is actually + assigned to the signal property. Trying to bind a value to a signal property will not work! - Signal parameters are also available to the executing script, as shown + Signal parameters are also available to the executing script, as shown below, as long as you remember to name the parameters of your signal in C++ (see QMetaMethod::parameterNames()). @@ -405,7 +405,7 @@ \row \o \code Example { - onDoSomething: for(var ii = 0; ii < count; ++ii) + onDoSomething: for(var ii = 0; ii < count; ++ii) print(message) } \endcode @@ -419,10 +419,10 @@ }; \endcode \endtable - + Just like property bindings, signal scripts are executed in a context. The signal script context is identical in scope to the "object context" under - property binding, with the exception that it has the signal parameters + property binding, with the exception that it has the signal parameters bound in. In addition to scripts, it is possible to assign objects to signal properties. @@ -439,9 +439,9 @@ \code Button { - id: MyButton + id: myButton onClicked: NumberAnimation { - target: MyButton + target: myButton property: "x" to: 100 } @@ -449,14 +449,14 @@ \endcode If the class itself actually defines a property called "on", this will - be assigned the string value and the signal handling behaviour will be + be assigned the string value and the signal handling behaviour will be disabled. \section1 Attached Properties Attached properties allow unrelated types to annotate another type with some additional properties. Some APIs or operations are inherintly imperative, - and attached properties help out when translating these APIs into the + and attached properties help out when translating these APIs into the declarative QML language. Qt's QGridLayout is one such example. @@ -484,7 +484,7 @@ } } \endcode - + Attached properties are identified by the use of a type name, in the case shown \c QGridLayout, as a grouped property specifier. To prevent ambiguity with actual class instantiations, attached properties must @@ -508,17 +508,17 @@ }; \endcode \endtable - + When an attached property is accessed, the QML engine will call this method to create an attachment object, passing in the object instance that the attached property applies to. The attachment object should define all the attached properties, and is generally parented to the provided object instance to avoid memory leaks. The QML engine does not saves this object, - so it is not necessary for the attached property function to ensure that + so it is not necessary for the attached property function to ensure that multiple calls for the same instance object return the same attached object. While conceptually simple, implementing an attachment object is not quite - so easy. The \c qmlAttachedProperties function is static - attachment + so easy. The \c qmlAttachedProperties function is static - attachment objects are not associated with any particular instance. How the values of the attached properties apply to the behaviour they are controlling is entirely implementation dependent. An additional consequence of this is @@ -537,13 +537,13 @@ The property has no effect because the (made-up) FancyGridLayout type defines the meaning of the \c row attached property only to apply to its direct children. It - is possible that other types may have attached properties that affect + is possible that other types may have attached properties that affect objects that aren't their direct children. - Attached properties are an advanced feature that should be used with + Attached properties are an advanced feature that should be used with caution. - \note We may implement a convenience wrapper that makes using attached + \note We may implement a convenience wrapper that makes using attached properties easier for the common "attach to children" case. \section1 Property Value Sources @@ -562,11 +562,11 @@ \endcode Here the \c x property of the rectangle will be animated from 0 to 100. - To support this, the NumberAnimation class inherits the + To support this, the NumberAnimation class inherits the QmlPropertyValueSource class. If a type inherits this class and is assigned to a property for which type assignment would otherwise fail (ie. the property itself doesn't have a type of QmlPropertyValueSource *), the QML - engine will automatically set the property as the target of the value + engine will automatically set the property as the target of the value source. \section1 Parser Status @@ -575,13 +575,13 @@ the appropriate properties, signals and slots and off you go. The QML engine takes care of instantiating your classes and setting the properties and everything works fine. - + However, sometimes it is helpful to know a little more about the status of - the QML parser. For example, it might be beneficial from a performance - standpoint to delay initializing some data structures until all the + the QML parser. For example, it might be beneficial from a performance + standpoint to delay initializing some data structures until all the properties have been set. - To assist with this, the QML engine defines an interface class called + To assist with this, the QML engine defines an interface class called QmlParserStatus. The interface defines a number of virtual methods that are invoked at various stages of the component instantiation. To receive these notifications, all a class has to do is to inherit the interface, and @@ -602,32 +602,32 @@ \section1 Extended Type Definitions - QML requires that types have the appropriate properties and signals to + QML requires that types have the appropriate properties and signals to work well within the declarative environment. In the case of existing - types, it is sometimes necessary to add signals, properties or slots to a - target class to make it more QML friendly but the original type cannot be - modified. For these cases, the QML engine supports extended type + types, it is sometimes necessary to add signals, properties or slots to a + target class to make it more QML friendly but the original type cannot be + modified. For these cases, the QML engine supports extended type definitions. An extended type definition allows the programmer to supply an additional type - known as the extension type - when registering the target class - whose properties, signals and slots are transparently merged with the + whose properties, signals and slots are transparently merged with the original target class when used from within QML. An extension class is a regular QObject, with a constructor that takes a - QObject pointer. When needed (extension classes are delay created + QObject pointer. When needed (extension classes are delay created until the first extension attribute is accessed) the extension class is created and the target object is passed in as the parent. When an extension attribute on the original is accessed, the appropriate signal, property or slots on the extension object is used instead. - When an extended type is installed, the + When an extended type is installed, the \code #define QML_DEFINE_EXTENDED_TYPE(T,QmlName,ExtendedTypeName) \endcode macro should be used instead of the regular \c QML_DEFINE_TYPE. - This example shows the addition of a read-only \c textLength property to + This example shows the addition of a read-only \c textLength property to QLabel being implemented as an extension. \table @@ -640,20 +640,20 @@ Q_PROPERTY(int textLength READ textLength) public: QWidgetExtension(QObject *parent) : QObject(parent) {} - int textLength() const { - return static_cast(parent())->text().count(); + int textLength() const { + return static_cast(parent())->text().count(); } }; QML_DEFINE_EXTENDED_TYPE(QLabel,QLabel,QLabelExtension); \endcode - \o + \o \code - QLabel { - id: Label1 + QLabel { + id: label1 text: "Hello World!" } - QLabel { - text: "Label1 text length: " + Label1.textLength + QLabel { + text: "label1 text length: " + label1.textLength } \endcode \endtable diff --git a/doc/src/declarative/qmlformat.qdoc b/doc/src/declarative/qmlformat.qdoc index f16adca..43eff05 100644 --- a/doc/src/declarative/qmlformat.qdoc +++ b/doc/src/declarative/qmlformat.qdoc @@ -7,20 +7,20 @@ \section1 Overview QML is an extension to \l {http://www.ecma-international.org/publications/standards/Ecma-262.htm} -{ECMAScript}. QML adds a mechanism for declaratively building a tree of objects, improved -integration between ECMAScript and Qt's existing QObject based type system, and support for -transparently maintained property value bindings between ECMAScript expressions and QObject +{ECMAScript}. QML adds a mechanism for declaratively building a tree of objects, improved +integration between ECMAScript and Qt's existing QObject based type system, and support for +transparently maintained property value bindings between ECMAScript expressions and QObject properties. Much of a QML file consists of valid ECMAScript \e {Statement}s. Except where constraints imposed by ECMAScript, C++ or QObject prevented it, the syntactic extensions introduced by QML are designed -to look similar and fit well with existing ECMAScript syntax and concepts. +to look similar and fit well with existing ECMAScript syntax and concepts. \section1 QML engine -The \l {QmlEngine}{QML engine} executes a \l {QmlComponent}{QML document} in a -\l {QmlContext}{QML context} to produce a \l {QObject}{QML object}. A single QML -document may be executed in one or many contexts to produce many QML objects. A single +The \l {QmlEngine}{QML engine} executes a \l {QmlComponent}{QML document} in a +\l {QmlContext}{QML context} to produce a \l {QObject}{QML object}. A single QML +document may be executed in one or many contexts to produce many QML objects. A single QML document may be executed many times in the same context to produce many QML objects. The QML engine provides the environment in which QML documents, contexts and objects @@ -34,10 +34,10 @@ and existing context properties cannot be modified. \i \e {QML object} will no longer evaluate bindings or scripts. \endlist -A QML document is a block of QML source code. QML documents generally correspond to files stored +A QML document is a block of QML source code. QML documents generally correspond to files stored on a disk or network resource, but can be constructed directly from text data. Syntactically a QML -document is self contained; QML does \bold {not} have a preprocessor that modifies the document -before presentation to the compiler. Type references within a QML document are resolved based +document is self contained; QML does \bold {not} have a preprocessor that modifies the document +before presentation to the compiler. Type references within a QML document are resolved based exclusively on the import statements present in the document. A simple QML document looks like this: @@ -49,7 +49,7 @@ A simple QML document looks like this: import Qt 4.6 Rectangle { - id: MyRect + id: myRect width: 100; height: 100 color: background } @@ -57,40 +57,40 @@ Rectangle { \endtable To instantiate a QML object, a QML document is executed in a QML context. QML contexts are used by -programmers to pass data to a QML document. QML documents may include property bindings or -ECMAScript blocks that can contain variable references that need to be resolved. Each property +programmers to pass data to a QML document. QML documents may include property bindings or +ECMAScript blocks that can contain variable references that need to be resolved. Each property binding and ECMAScript block has an associated QML context that is used to resolve these references that is determined by the QML context in which the document is executed. The example document above -contains one variable reference, \c background. +contains one variable reference, \c background. Each QML context defines a scope for variable resolution and each may define local, named context -properties. A QML context may also have a \l {QmlContext::addDefaultObject()}{default object}, -which is an object whose properties are searched \e after the context properties when resolving a -variable name. QML contexts form a tree, starting from a root context that is provided by the QML +properties. A QML context may also have a \l {QmlContext::addDefaultObject()}{default object}, +which is an object whose properties are searched \e after the context properties when resolving a +variable name. QML contexts form a tree, starting from a root context that is provided by the QML engine. When resolving variable references, the QML contexts are searched starting from the QML objects containing context upwards towards the root context. -Consider the following QML context tree. If the example QML document is executed in \c Context1, -the \c background variable will resolve to \c Context1's context property. If the document is -executed in \c Context2, the \c background variable will resolve to the root context's context +Consider the following QML context tree. If the example QML document is executed in \c Context1, +the \c background variable will resolve to \c Context1's context property. If the document is +executed in \c Context2, the \c background variable will resolve to the root context's context property. \image qml-context-tree.png While QML contexts can be created explicitly by the programmer to pass data into QML objects, the QML engine also creates a new implicit QML context for every object it instantiates. -Property bindings and ECMAScript blocks in the document are associated with this QML engine -created context. Object ids that are defined in the document are added as context properties, and +Property bindings and ECMAScript blocks in the document are associated with this QML engine +created context. Object ids that are defined in the document are added as context properties, and their value is set to reference the appropriate object, and the instantiated QML object is set as -the context's default object. The following diagram shows the result of executing a simple QML +the context's default object. The following diagram shows the result of executing a simple QML document. \image qml-context-object.png -The blue rectangle in the diagram represents a property binding. Associated with each property +The blue rectangle in the diagram represents a property binding. Associated with each property binding is the QML context to which it belongs, the object property to which it is bound and a -\e {scope object}. The scope object is usually, but not always, the object to which the bound -property belongs. The context properties, context default objects and the scope object are all +\e {scope object}. The scope object is usually, but not always, the object to which the bound +property belongs. The context properties, context default objects and the scope object are all involved when resolving a variable name in a binding. The following pseudo code describes the algorithm used: @@ -112,14 +112,14 @@ foreach (context in contextChain) { \endtable QML supports two categories of types: \e builtin types and \e composite types. Builtin types are -those written in C++ and registered with the QML engine. Builtin types form the most basic -building blocks of QML. Composite types are constructed by composing other builtin or composite -types, property bindings and ECMAScript blocks together into a brand new type using the QML +those written in C++ and registered with the QML engine. Builtin types form the most basic +building blocks of QML. Composite types are constructed by composing other builtin or composite +types, property bindings and ECMAScript blocks together into a brand new type using the QML language. Using a composite type is identical to using a builtin type. -For example, Qt 4.6 includes a builtin type called \c Image that shows a bitmap image. The +For example, Qt 4.6 includes a builtin type called \c Image that shows a bitmap image. The \c Image type has \c width and \c height properties that control the size of the displayed image. -A simple composite type, that will be called \c SquareImage can be built that adds a \c size +A simple composite type, that will be called \c SquareImage can be built that adds a \c size property that sets both the width and the height. \table @@ -129,22 +129,22 @@ property that sets both the width and the height. import Qt 4.6 Image { property int size - width: size - height: size + width: size + height: size } \endcode \endtable To the QML engine, a composite type is just another QML document. When a composite type is used the engine instantiates it just as it would any other document - by creating a new implicit -QML context and the object tree described by the document. The diagram below shows the +QML context and the object tree described by the document. The diagram below shows the \c SquareImage composite type used from within another QML document. When instantiated, the \c SquareImage object is created in its own QML context. Any property bindings specified in the \c SquareImage composite type document are associated with this context. Property bindings created in the outer document, however, are associated with its context, even those that are applied to the created \c SquareImage object. That is, the \c size, \c source, \c width and \c height property bindings all share a common \e {scope object}, but are owned by two different QML contexts. The -difference in containing context results in the \c Root variable resolving differently in the +difference in containing context results in the \c Root variable resolving differently in the different property bindings. \image qml-context.png @@ -173,7 +173,7 @@ The commenting rules in QML are the same as for ECMAScript. Both \e {MultiLineC \e {QMLImportStatement} \bold {:} \quotation -\bold {import} \e {StringLiteral} +\bold {import} \e {StringLiteral} \bold {import} \e {StringLiteral} \e {QMLVersionNumber} @@ -198,8 +198,8 @@ The commenting rules in QML are the same as for ECMAScript. Both \e {MultiLineC \section3 Semantics -The \e {QMLImportList} is used to statically resolve type references used within the enclosing -QML document. +The \e {QMLImportList} is used to statically resolve type references used within the enclosing +QML document. An import statement is used to bring a set of types into scope for a QML document. diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc index ef84b8e..cfefdb9 100644 --- a/doc/src/declarative/qmlintro.qdoc +++ b/doc/src/declarative/qmlintro.qdoc @@ -80,11 +80,11 @@ expression has been assigned to is automatically updated to that value. \code Item { Text { - id: Text1 + id: text1 text: "Hello World" } Text { - id: Text2 + id: text2 text: Text1.text } } @@ -138,7 +138,7 @@ real, bool, string, color, and lists. Item { x: 10.5 // a 'real' property ... - state: "Details" // a 'string' property + state: "details" // a 'string' property focus: true // a 'bool' property } \endcode @@ -161,16 +161,16 @@ to refer to it elsewhere. \code Item { Text { - id: MyName + id: myName text: "..." } Text { - text: MyName.text + text: myName.text } } \endcode -\c ids must begin with a letter. We recommend that you start your ids with a capital letter. +\c Ids must begin with a lowercase letter. \section2 List properties -- cgit v0.12 From 5bc98da76b7d6ab4d175ac75e539d7f887c2c080 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 18:15:15 +1000 Subject: Fix test case qWait() enters a nested event loop, so delete laters weren't being processed. --- tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 34fa5e9..4ed12f7 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -667,6 +667,7 @@ void tst_qmlecmascript::dynamicDestruction() QMetaObject::invokeMethod(object, "killMe"); QVERIFY(object); QTest::qWait(0); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); QVERIFY(!object); } -- cgit v0.12 From 12f272ce159853329a26fc82dfb55b930a97a2a9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 18:20:40 +1000 Subject: Remove bogus assert --- src/declarative/qml/qmlobjectscriptclass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index ce74aef..9448dcc 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -186,7 +186,6 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name else if (name == m_toStringId.identifier) return m_toString; - Q_ASSERT(lastData); Q_ASSERT(obj); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); -- cgit v0.12 From 8a54ed9524befc4a172cdc19a18d9953f3a01df0 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 7 Oct 2009 18:22:46 +1000 Subject: typos --- doc/src/declarative/advtutorial1.qdoc | 2 +- doc/src/declarative/advtutorial2.qdoc | 2 +- doc/src/declarative/advtutorial3.qdoc | 8 ++++---- doc/src/declarative/advtutorial4.qdoc | 6 +++--- doc/src/declarative/tutorial1.qdoc | 2 +- doc/src/declarative/tutorial2.qdoc | 2 +- doc/src/declarative/tutorial3.qdoc | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/src/declarative/advtutorial1.qdoc b/doc/src/declarative/advtutorial1.qdoc index 48b32cd..f9c1f93 100644 --- a/doc/src/declarative/advtutorial1.qdoc +++ b/doc/src/declarative/advtutorial1.qdoc @@ -1,8 +1,8 @@ /*! \page advtutorial1.html \example declarative/tutorials/samegame/samegame1 -\title Advanced Tutorial 1 - Creating the Game canvas and block \target advtutorial1 +\title Advanced Tutorial 1 - Creating the Game canvas and block The first step is to create the items in your application. In Same Game we have a main game screen and the blocks that populate it. diff --git a/doc/src/declarative/advtutorial2.qdoc b/doc/src/declarative/advtutorial2.qdoc index 2d2fe19..4a6bb06 100644 --- a/doc/src/declarative/advtutorial2.qdoc +++ b/doc/src/declarative/advtutorial2.qdoc @@ -1,7 +1,7 @@ /*! \page advtutorial2.html -\title Advanced Tutorial 2 - Populating the Game Canvas \target advtutorial2 +\title Advanced Tutorial 2 - Populating the Game Canvas Now that we've written some basic elements, let's start writing the game. The first thing to do is to generate all of the blocks. Now we need to dynamically diff --git a/doc/src/declarative/advtutorial3.qdoc b/doc/src/declarative/advtutorial3.qdoc index 635054b..ffdc960 100644 --- a/doc/src/declarative/advtutorial3.qdoc +++ b/doc/src/declarative/advtutorial3.qdoc @@ -1,9 +1,9 @@ /*! \page advtutorial3.html -\title Advanced Tutorial 3 - Implementing the Game Logic \target advtutorial3 +\title Advanced Tutorial 3 - Implementing the Game Logic -To the initBoard function we added clearing the board before hand, so that clicking new game won't leave the previous game lying around in the background. To the createComponent function we have added setting the type of the block to a number between one and three - it's fundamental to the game logic that the blocks be different types if you want a fun game. +To the initBoard function we added clearing the board beforehand, so that clicking new game won't leave the previous game lying around in the background. To the createComponent function we have added setting the type of the block to a number between one and three - it's fundamental to the game logic that the blocks be different types if you want a fun game. The main change was adding the following game logic functions: \list @@ -23,9 +23,9 @@ You'll notice them referring to the 'gameCanvas' item. This is an item that has \snippet declarative/tutorials/samegame/samegame3/samegame.qml 1 -This item is the exact size of the board, contains a score property, and a mouse region for input. The blocks are now created as its children, and its size is used as the noe determining board size. Since it needs to bind its size to a multiple of tileSize, tileSize needs to be moved into a QML property and out of the script file. It can still be accessed from the script. +This item is the exact size of the board, contains a score property, and a mouse region for input. The blocks are now created as its children, and its size is used to determining the board size. Since it needs to bind its size to a multiple of tileSize, tileSize needs to be moved into a QML property and out of the script file. It can still be accessed from the script. -The mouse region simply calls handleClick(), which deals with the input events.Should those events cause the player to score, gameCanvas.score is updated. The score display text item has also been changed to bind its text property to gamecanvas.score. Note that if score was a global variable in the samegame.js file yo ucould not bind to it. You can only bind to QML properties. +The mouse region simply calls handleClick(), which deals with the input events. Should those events cause the player to score, gameCanvas.score is updated. The score display text item has also been changed to bind its text property to gamecanvas.score. Note that if score was a global variable in the samegame.js file you could not bind to it. You can only bind to QML properties. victoryCheck() mostly just updates score. But it also pops up a dialog saying 'Game Over' when the game is over. In this example we wanted a pure-QML, animated dialog, and since the Fx primitives set doesn't contain one, we wrote our own. Below is the code for the Dialog element, note how it's designed so as to be quite usable imperatively from within the script file: diff --git a/doc/src/declarative/advtutorial4.qdoc b/doc/src/declarative/advtutorial4.qdoc index 291d2f2..ae38c5e 100644 --- a/doc/src/declarative/advtutorial4.qdoc +++ b/doc/src/declarative/advtutorial4.qdoc @@ -1,7 +1,7 @@ /*! \page advtutorial4.html -\title Advanced Tutorial 4 - Finishing Touches \target advtutorial4 +\title Advanced Tutorial 4 - Finishing Touches Now we're going to do two things to liven the game up. Animate the blocks and add a web-based high score system. @@ -9,7 +9,7 @@ If you compare the samegame3 directory with samegame4, you'll noticed that we've \section2 Animated Blocks -The most vital animations are that the blocks move fluidly around the board. QML has many tools for fluid behavior, and in this case we're going to use the Follow element. By having the script set targetX and targetY, instead of x and y directly, we can set the x and y of the block to a follow. SpringFollow is a property value source, which means that you can set a property to be one of these elements and it will automatically bind the property to the element's value. The SpringFollow's value follows another value over time, when the value it is tracking changes the SpringFollow's value will also change, but it will move smoothly there over time with a spring-like movement (based on the spring parameters specified). This is shown in the below snippet of code from Block.qml: +The most vital animations are that the blocks move fluidly around the board. QML has many tools for fluid behavior, and in this case we're going to use the SpringFollow element. By having the script set targetX and targetY, instead of x and y directly, we can set the x and y of the block to a follow. SpringFollow is a property value source, which means that you can set a property to be one of these elements and it will automatically bind the property to the element's value. The SpringFollow's value follows another value over time, when the value it is tracking changes the SpringFollow's value will also change, but it will move smoothly there over time with a spring-like movement (based on the spring parameters specified). This is shown in the below snippet of code from Block.qml: \code property int targetX: 0 @@ -19,7 +19,7 @@ The most vital animations are that the blocks move fluidly around the board. QML y: SpringFollow { source: targetY; spring: 2; damping: 0.2 } \endcode -We also have to change the samegame.js code, so that wherever it was setting the x or y it now sets targetX and targetY (including when creating the block). This simple change is all you need to get spring moving blocks that no longer teleport around the board. If you try doing just this though, you'll notice that they now never jump from one point to another, even in the initialization! This gives an odd effect of having them all jump out of the corner (0,0) on start up. We'd rather that they fall down from the top in rows. To do this, we disable the x Follow (but not the y follow) and only enable it after we've set the x in the createBlock function. The above snippet now becomes: +We also have to change the samegame.js code, so that wherever it was setting the x or y it now sets targetX and targetY (including when creating the block). This simple change is all you need to get spring moving blocks that no longer teleport around the board. If you try doing just this though, you'll notice that they now never jump from one point to another, even in the initialization! This gives an odd effect of having them all jump out of the corner (0,0) on start up. We'd rather that they fall down from the top in rows. To do this, we disable the x follow (but not the y follow) and only enable it after we've set the x in the createBlock function. The above snippet now becomes: \snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 1 diff --git a/doc/src/declarative/tutorial1.qdoc b/doc/src/declarative/tutorial1.qdoc index d4f1095..e6232af 100644 --- a/doc/src/declarative/tutorial1.qdoc +++ b/doc/src/declarative/tutorial1.qdoc @@ -1,7 +1,7 @@ /*! \page tutorial1.html -\title Tutorial 1 - Hello World! \target tutorial1 +\title Tutorial 1 - Hello World! This first program is a simple "Hello world" example. The picture below is a screenshot of this program. diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc index c6fd06b..c97fddf 100644 --- a/doc/src/declarative/tutorial2.qdoc +++ b/doc/src/declarative/tutorial2.qdoc @@ -1,7 +1,7 @@ /*! \page tutorial2.html -\title Tutorial 2 - Some colors \target tutorial2 +\title Tutorial 2 - Some colors This chapter adds a color picker to change the color of the text. diff --git a/doc/src/declarative/tutorial3.qdoc b/doc/src/declarative/tutorial3.qdoc index a0d842c..bce7e92 100644 --- a/doc/src/declarative/tutorial3.qdoc +++ b/doc/src/declarative/tutorial3.qdoc @@ -1,7 +1,7 @@ /*! \page tutorial3.html -\title Tutorial 3 - States \target tutorial3 +\title Tutorial 3 - States In this chapter, we make this example a little bit more dynamic by introducing states. -- cgit v0.12 From d07270161ef3d1c4b3ed29110a16eaff54333fd5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 22:07:06 +1000 Subject: Fix test case qWait() enters a nested event loop, so delete laters weren't being processed. --- tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 4ed12f7..51f1ce7 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -660,8 +660,10 @@ void tst_qmlecmascript::dynamicDestruction() QMetaObject::invokeMethod(object, "killOther"); QVERIFY(createdQmlObject); QTest::qWait(0); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); QVERIFY(createdQmlObject); QTest::qWait(100); + QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion); QVERIFY(!createdQmlObject); QMetaObject::invokeMethod(object, "killMe"); -- cgit v0.12 From dd2f8a3224abff4f6528a23c821c44cbbf282073 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 10:02:46 +1000 Subject: Font-portable. --- .../declarative/visual/easing/data/easing.0.png | Bin 20526 -> 3395 bytes .../declarative/visual/easing/data/easing.1.png | Bin 20526 -> 3379 bytes .../declarative/visual/easing/data/easing.2.png | Bin 20526 -> 3101 bytes .../declarative/visual/easing/data/easing.3.png | Bin 0 -> 16542 bytes .../auto/declarative/visual/easing/data/easing.qml | 498 +++++++++------------ tests/auto/declarative/visual/easing/easing.qml | 23 +- 6 files changed, 220 insertions(+), 301 deletions(-) create mode 100644 tests/auto/declarative/visual/easing/data/easing.3.png diff --git a/tests/auto/declarative/visual/easing/data/easing.0.png b/tests/auto/declarative/visual/easing/data/easing.0.png index fa078ae..2f1b5f6 100644 Binary files a/tests/auto/declarative/visual/easing/data/easing.0.png and b/tests/auto/declarative/visual/easing/data/easing.0.png differ diff --git a/tests/auto/declarative/visual/easing/data/easing.1.png b/tests/auto/declarative/visual/easing/data/easing.1.png index fa078ae..59083bd 100644 Binary files a/tests/auto/declarative/visual/easing/data/easing.1.png and b/tests/auto/declarative/visual/easing/data/easing.1.png differ diff --git a/tests/auto/declarative/visual/easing/data/easing.2.png b/tests/auto/declarative/visual/easing/data/easing.2.png index fa078ae..20c73c8 100644 Binary files a/tests/auto/declarative/visual/easing/data/easing.2.png and b/tests/auto/declarative/visual/easing/data/easing.2.png differ diff --git a/tests/auto/declarative/visual/easing/data/easing.3.png b/tests/auto/declarative/visual/easing/data/easing.3.png new file mode 100644 index 0000000..c68e0fa Binary files /dev/null and b/tests/auto/declarative/visual/easing/data/easing.3.png differ diff --git a/tests/auto/declarative/visual/easing/data/easing.qml b/tests/auto/declarative/visual/easing/data/easing.qml index c41d676..d5beeef 100644 --- a/tests/auto/declarative/visual/easing/data/easing.qml +++ b/tests/auto/declarative/visual/easing/data/easing.qml @@ -6,862 +6,774 @@ VisualTest { } Frame { msec: 16 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 32 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 48 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 64 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 80 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 96 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 112 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 128 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 144 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 160 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 176 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 192 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 208 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 224 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 240 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 256 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 272 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 111; y: 419 + modifiers: 0 + sendToViewport: true } Frame { msec: 288 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 304 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 320 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "8f4c40d2e2b4f064bcb77c5ae43928c6" } Frame { msec: 336 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "8b65094a9b7d5394fc67f92ea058627f" } Frame { msec: 352 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "da450826b471a60ba98dabc581631ba1" } Frame { msec: 368 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "e820fb4f1bc97152aa940b07db549f1b" } Frame { msec: 384 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "b7d8186beca2fa0e37099f72419350f4" } Frame { msec: 400 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "8500b93774f214e5e4789e25500262b8" } Frame { msec: 416 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "277e1dff70285cca536b3e1fc2590688" } Frame { msec: 432 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "b05b18f92c2089c681661566117ae0f5" } Frame { msec: 448 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "6fec9c6b6ac3e3ea4126e3824a8d7566" } Frame { msec: 464 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "53c6c90dd1eb7ca47721fc116474aebf" } Frame { msec: 480 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "cf729c4a31414af3d2705878ba615738" } Frame { msec: 496 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Mouse { - type: 2 - button: 1 - buttons: 1 - x: 293; y: 405 - modifiers: 0 - sendToViewport: true + hash: "f146b8a68960d507f893ef001189220e" } Frame { msec: 512 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "18ff56b870bb048af246f928ee42a9b0" } Frame { msec: 528 - hash: "b7f8cf8b426db83a5a4cc1f673650842" + hash: "beee98f73fe7e878ada37b3070fa0c1d" } Frame { msec: 544 - hash: "f9a41aaf57b18271d467b73e609c8a28" + hash: "435d389082912950a0be2b5dff480319" } Frame { msec: 560 - hash: "2607ceafe74863a4810fc11754be7745" + hash: "dc39b080eaddeaf4e309b90b7d97a835" } Frame { msec: 576 - hash: "c80df114e67af7c9c4d61917938bba60" - } - Mouse { - type: 3 - button: 1 - buttons: 0 - x: 293; y: 405 - modifiers: 0 - sendToViewport: true + hash: "666b1cde53f78d7db9c81e21adbe406a" } Frame { msec: 592 - hash: "c80df114e67af7c9c4d61917938bba60" + hash: "c5c9627f4329e48aa96ebfbc982b6ba6" } Frame { msec: 608 - hash: "c80df114e67af7c9c4d61917938bba60" + hash: "a583042052e5da7e80a4956337d6d1ff" } Frame { msec: 624 - hash: "21fb97b78a419db73303a01ae99820ea" + hash: "a4a5df787e15da6f28275a12898e7620" } Frame { msec: 640 - hash: "2b3878b2698798e94a9fcf429be908d0" + hash: "02cacec2ccc803ebc03c5540484cbcaa" } Frame { msec: 656 - hash: "78ce8b817edec30801720203b01eefa8" + hash: "00600df1f006f358feaf43bfae9d32a5" } Frame { msec: 672 - hash: "2560e4300b06cf33dcd58880ddb298f3" + hash: "737c884ba0d6d38b66252f4b97a36c33" } Frame { msec: 688 - hash: "2a25abaa2b0ce9b5b39b2fa04ef4c77d" + hash: "7eeeade8100c84a6b56efa51cf597baf" } Frame { msec: 704 - hash: "52bd37c4dc3ba8ebf8152b0f1e35e4b0" + hash: "18ab79d495097f0103dcf14db1897a88" } Frame { msec: 720 - hash: "6921eb51b6d967980adc28d964d5a88f" + hash: "21d3b0da00c46a101e09048928cd8027" } Frame { msec: 736 - hash: "b6d8f7879a170a0311a3f4689388dd40" + hash: "a5995b0341872c275ffbc5aaee6eb853" } Frame { msec: 752 - hash: "7ebefa6c5ce5dd18d3df566fd9f396fe" + hash: "bb4a37c1bd5e412ebce54d9539017723" } Frame { msec: 768 - hash: "8c097cf34a1af48e336581c01f166978" + hash: "63dcde9e2751ca94ed7d739feb359221" } Frame { msec: 784 - hash: "2a28843361f763ba83b02a0c8ef5094b" + hash: "5790c8407e2e4d1a6a937d86d57d8edb" } Frame { msec: 800 - hash: "07d699dc6dc9e3013a83dff04ae0956e" + hash: "3a1c77abf6822030db60a036027dc86e" } Frame { msec: 816 - hash: "09935d52bf4602cbdc06c6e5e755bc64" + hash: "2a13c573ab9846cce60384dd7138b2b4" } Frame { msec: 832 - hash: "fcad934f3cf4f542ab8cd70ef3915e44" + hash: "98983c2525265830033495b61071a5aa" } Frame { msec: 848 - hash: "602bfdd9831ef1facb42e031c545749f" + hash: "26d2bba3d77053b410715afb497d4063" } Frame { msec: 864 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "fd65d954c16acee425d9de65af68ef40" } Frame { msec: 880 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "094fcc18d28b19ac6b452dd8106d813b" } Frame { msec: 896 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "160105f6f99a960763535e4d51990ef6" } Frame { msec: 912 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "0d5d1e6a66fc1f49f1106f01fb5a1c52" } Frame { msec: 928 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "f6abc32680865783a4d94ecb738f9ff6" } Frame { msec: 944 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "350509eceb134d5b18647e5ad07dbb47" } Frame { msec: 960 - image: "easing.0.png" + image: "/home/wallison/qt/kinetic/tests/auto/declarative/visual/easing/data/easing.0.png" } Frame { msec: 976 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "4c9de74276d32c5b2787cf75e612f97d" } Frame { msec: 992 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "efcc5ae79da3fa2f4c7d6eaa35e32d33" } Frame { msec: 1008 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "ff4afce604c8ecb4f08d1ddef8552534" } Frame { msec: 1024 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "e2e63e12e9a5f8459720dd8b023ed17b" } Frame { msec: 1040 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "991a01f92bcfa9cd9fe98e3f39d192fc" } Frame { msec: 1056 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bc3d2f0f3fac650c981457f3694c2518" } Frame { msec: 1072 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "ee39fc9b1a602bf813d9118aa21901ac" } Frame { msec: 1088 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "42120d098f2adf1e331332b33442dd3e" } Frame { msec: 1104 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "1660c69b77b800d1ab57b93f0fc12aa5" } Frame { msec: 1120 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "0630a3d6b8cb5dece5dc660f05036ec6" } Frame { msec: 1136 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9163f0bd9c5888794d7a09d3359bf1e5" } Frame { msec: 1152 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "e0b7ad4883f679948c852ff152ba7907" } Frame { msec: 1168 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "f748fc44f99b706e42b899cb18dbaaf7" } Frame { msec: 1184 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "c84442f0cb1cf0bb50dae7d1c701aaf8" } Frame { msec: 1200 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "d7b41567e3f3aa9576fe2793872134b7" } Frame { msec: 1216 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a1d10ff1adb85000902486fc8e4faa8d" } Frame { msec: 1232 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "44b7b5d77068e360ead3af84e7d80232" } Frame { msec: 1248 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "486c0b19c1379d9eefdf575a085e2875" } Frame { msec: 1264 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "1d474472856d4740d960eb2f788ca5a6" } Frame { msec: 1280 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "c74082553ab0f4ee00f5044e3369580b" } Frame { msec: 1296 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "89fcd5514f336075ad32cae69518c1e5" } Frame { msec: 1312 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1328 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1344 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1360 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1376 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1392 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Mouse { - type: 2 - button: 1 - buttons: 1 - x: 293; y: 405 - modifiers: 0 - sendToViewport: true + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1408 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1424 - hash: "b7f8cf8b426db83a5a4cc1f673650842" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1440 - hash: "f9a41aaf57b18271d467b73e609c8a28" - } - Mouse { - type: 3 - button: 1 - buttons: 0 - x: 293; y: 405 - modifiers: 0 - sendToViewport: true + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1456 - hash: "f9a41aaf57b18271d467b73e609c8a28" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1472 - hash: "f9a41aaf57b18271d467b73e609c8a28" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1488 - hash: "6837618bfafa541897d1f749de527ef0" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1504 - hash: "c50ce6e3c3a212d2ffdb72a1d3588f42" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1520 - hash: "33c6a60e9e82a01055202dd937db2770" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1536 - hash: "c8d2e502901da8f44eaf9684e1a4adea" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1552 - hash: "d51c5f7c9bac986a9c2ce7323a69f864" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1568 - hash: "687214f92a4cc60c5208a59a7824e30e" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1584 - hash: "7fe974f28880037ec592c0525468248a" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1600 - hash: "c7aa4f0ffbc0b5e231cce0c75dec7a97" + hash: "9dd235eb98998d9bdd92e01300297257" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 111; y: 419 + modifiers: 0 + sendToViewport: true } Frame { msec: 1616 - hash: "7000e685420a3fbf1d3d7d22b745c58f" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1632 - hash: "3f85aa08cf725234319ab01ff16b4bff" + hash: "9dd235eb98998d9bdd92e01300297257" } Frame { msec: 1648 - hash: "326347eb8a01236464140bbcc84745a7" + hash: "b77240f32e83d4f332d815c626f1e560" } Frame { msec: 1664 - hash: "e0fed8a1bc453b09df05ff9a5326b38a" + hash: "7d89669231224cf8e02d75338c37c278" } Frame { msec: 1680 - hash: "a81d7fb7673449a38579baf879313b63" + hash: "a8cf7c179011ee8187a8e1111683e52e" } Frame { msec: 1696 - hash: "69235e99941bf5d6c50fbe6dbbda5945" + hash: "3e87a57e05da09a8260801320431b922" } Frame { msec: 1712 - hash: "346e107de2853c5b1ba74411ceafaf8d" + hash: "a2b0d99c8a232715fe03e8772a36634c" } Frame { msec: 1728 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "5b4634cd495ae7bb9c69a5c9c346189e" } Frame { msec: 1744 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "492f8f2b84af355ef41c1a7cda3a8a73" } Frame { msec: 1760 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "88e4eb08520fb5acc3d88ac4f0900542" } Frame { msec: 1776 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "0c09cdcb906b4ce9840fd7502c39e5b9" } Frame { msec: 1792 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "b054083bdd212cc03167a90df2d7eac5" } Frame { msec: 1808 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "83971c2d37616ab92680364d6ac288a6" } Frame { msec: 1824 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a73951d25e2cb7c1d04c88c86dfa0e4d" } Frame { msec: 1840 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "31fc8b20302abac97e506c37a14bbb7e" } Frame { msec: 1856 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "f760ccd7339e01a9423da7b592498291" } Frame { msec: 1872 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "24dfcd5553f854908396de751fb15b88" } Frame { msec: 1888 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "1daf38a6e6199f980e9494a3eb480047" } Frame { msec: 1904 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a39e2de1090209e5dbc8cc26577ec97d" } Frame { msec: 1920 - image: "easing.1.png" + image: "/home/wallison/qt/kinetic/tests/auto/declarative/visual/easing/data/easing.1.png" } Frame { msec: 1936 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "2d2ce71a074f045916a207044abd055a" } Frame { msec: 1952 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a19b0353604491f56f72be0d20d76955" } Frame { msec: 1968 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "9a70f109eebfcede2311ef77ceb50a44" } Frame { msec: 1984 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "7b28313d6860aeefd4a4e136d38d62f8" } Frame { msec: 2000 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "95d84f38473159fe6b38f84ffe371714" } Frame { msec: 2016 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "07f91261794edb0ac1fde9bb4ff36011" } Frame { msec: 2032 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "f9a4a6b92a9c2d265688f1bfac18fa0a" } Frame { msec: 2048 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "cdec7cc00380fde4f73be997a992251a" } Frame { msec: 2064 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a52b34f84e98fcd8babb1d39979fc9c7" } Frame { msec: 2080 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bf05b3c79a9616f2e6c33d348b30e0ba" } Frame { msec: 2096 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "c5931785685b4f4854d3ddfff5dd5466" } Frame { msec: 2112 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Mouse { - type: 2 - button: 1 - buttons: 1 - x: 294; y: 405 - modifiers: 0 - sendToViewport: true + hash: "bae163e02b860a9ca19d1bcb60ac1f8e" } Frame { msec: 2128 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a36295a1ebb35e538f8899ae3ae3b36a" } Frame { msec: 2144 - hash: "b7f8cf8b426db83a5a4cc1f673650842" + hash: "b6448d61803d9b2c05b438aa8ce8bcd5" } Frame { msec: 2160 - hash: "f9a41aaf57b18271d467b73e609c8a28" + hash: "631bf4caff2d93ef96a426100ffc5b32" } Frame { msec: 2176 - hash: "2607ceafe74863a4810fc11754be7745" + hash: "a8777c84a03996493f719f5fcfc80d00" } Frame { msec: 2192 - hash: "c80df114e67af7c9c4d61917938bba60" + hash: "86e1759df103ef776bb03f24941f49da" } Frame { msec: 2208 - hash: "b33f77efd04ccde252fefbf2d8a0cd60" - } - Mouse { - type: 3 - button: 1 - buttons: 0 - x: 294; y: 405 - modifiers: 0 - sendToViewport: true + hash: "01a790ea60adeaf368c66bd53aa8fcb3" } Frame { msec: 2224 - hash: "b33f77efd04ccde252fefbf2d8a0cd60" + hash: "79e5aca8ef6b9764f7f99cdfb51222ae" } Frame { msec: 2240 - hash: "b33f77efd04ccde252fefbf2d8a0cd60" + hash: "82d10cc01b9be4683c5aa76096bd462c" } Frame { msec: 2256 - hash: "fd993a41d312ccfdbd6206a4f33aaa5f" + hash: "95d961a92c597e432611947f7480796a" } Frame { msec: 2272 - hash: "27a704ddc65928d6c7732c14d357b796" + hash: "e8ee89b5313c7e2c66741fe1c2090029" } Frame { msec: 2288 - hash: "7f466d3d85a94178b2e9e06cee9cb35d" + hash: "2e3e8cf25dc1a3f09e7bf2a086f8e3bb" } Frame { msec: 2304 - hash: "2fc08efcc8e8daaf0b0f85bbca3b1b9e" + hash: "68ca8ad381f48db23d2bc5da9da0c17a" } Frame { msec: 2320 - hash: "8b4d5586c8ebf5654156251c46479c61" + hash: "e29f2411667049e8fae6c080f61c5869" } Frame { msec: 2336 - hash: "50cbc5513143056667645d5ea25aceab" + hash: "5b0a6fadedf3024e8ecb7f2c73a2277d" } Frame { msec: 2352 - hash: "2e59236e75e7cc97c25b6eb816c9a116" + hash: "af2eac625ef1fd928093ccd60bc0058e" } Frame { msec: 2368 - hash: "f865be9e69de683a150d3a43ae740c1b" + hash: "8a1ff780ebdc9e416e60ea0940e8f2d6" } Frame { msec: 2384 - hash: "816d3ed67a449dcaf71f5c82b07c0d7c" + hash: "7eb316c51cfd8ad972b7040247a651eb" } Frame { msec: 2400 - hash: "5271565364560bed69fddf75b1945a94" + hash: "1bac7075c10c87a69e71c3859f0db41d" } Frame { msec: 2416 - hash: "e89015974ae8e05ae524dc51f1724494" + hash: "0f16f40567729065cf9ecfcc15395a7b" } Frame { msec: 2432 - hash: "fd0b8d6d4540eeebc22c25f592fdcf77" + hash: "719f4e776776f0db5c68ae7c6177e9b7" } Frame { msec: 2448 - hash: "35348763f8d2fb13e1421e9f796f46a8" + hash: "75172dbf31fd8d706f54748c59099845" } Frame { msec: 2464 - hash: "6c73c47b5b3a9db6cd73c0167125774b" + hash: "d730b550e05167b05350e0e6636dd97d" } Frame { msec: 2480 - hash: "f3e947a709bb949eb9e31223aa83e696" + hash: "e1f33eb5f023d9d42a99f8bc23223c45" } Frame { msec: 2496 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "8a4b0df5bed6c7be73c194ce2bb6a271" } Frame { msec: 2512 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "44a9ea371f12d4ac3a569121a995ae16" } Frame { msec: 2528 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "14747e2e9e072210b9d6db50b4f704a1" } Frame { msec: 2544 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "eea52abf430f8cc1adc37e7180036584" } Frame { msec: 2560 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "0a9f6b14bc02e929a45bf4ebb736f9d3" } Frame { msec: 2576 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "a68a6eef0fc8754564c47c88b60d9a2a" } Frame { msec: 2592 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "eeb469e2fbda131d83538055e88ecdf7" } Frame { msec: 2608 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "0f7b673472050e807c9d935fde5afd83" } Frame { msec: 2624 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "80c90cce66bdd2324ca98bc591c22b44" } Frame { msec: 2640 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2656 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2672 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2688 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2704 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2720 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2736 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2752 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2768 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2784 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2800 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2816 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2832 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2848 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2864 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2880 - image: "easing.2.png" + image: "/home/wallison/qt/kinetic/tests/auto/declarative/visual/easing/data/easing.2.png" } Frame { msec: 2896 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2912 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2928 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2944 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2960 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2976 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 2992 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 3008 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } Frame { msec: 3024 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3040 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Key { - type: 6 - key: 16777249 - modifiers: 67108864 - text: "" - autorep: false - count: 1 - } - Frame { - msec: 3056 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3072 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3088 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3104 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3120 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3136 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3152 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3168 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3184 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3200 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" - } - Frame { - msec: 3216 - hash: "fb57b2d47ca82a5f1301aac14c8ff67e" + hash: "bb8e2ba14526dc5ad74f74e8ff3d96a5" } } diff --git a/tests/auto/declarative/visual/easing/easing.qml b/tests/auto/declarative/visual/easing/easing.qml index 1448064..f81400b 100644 --- a/tests/auto/declarative/visual/easing/easing.qml +++ b/tests/auto/declarative/visual/easing/easing.qml @@ -140,18 +140,24 @@ Rectangle { Repeater { model: easingtypes Component { - Text { - id: text - text: type + Rectangle { + id: block + Text { + text: type + anchors.centerIn: parent + font.italic: true + color: index & 1 ? "black" : "white" + opacity: 0 // 1 for debugging + } + width: 120 height: 18 - font.italic: true - color: "black" + color: index & 1 ? "red" : "blue" states: [ State { name: "from" when: !mouse.pressed PropertyChanges { - target: text + target: block x: 0 } }, @@ -159,8 +165,8 @@ Rectangle { name: "to" when: mouse.pressed PropertyChanges { - target: text - x: item.width-100 + target: block + x: item.width-block.width } } ] @@ -172,6 +178,7 @@ Rectangle { NumberAnimation { properties: "x" easing: type + duration: 1000 } } ] -- cgit v0.12 From 4cd7e2a0a956b1f9a0ea0d4691ebb1380ebc7c84 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 8 Oct 2009 10:40:05 +1000 Subject: doc cleanup --- doc/src/declarative/anchor-layout.qdoc | 2 +- doc/src/declarative/focus.qdoc | 2 +- doc/src/declarative/qmlintro.qdoc | 1 + doc/src/declarative/tutorial2.qdoc | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc index e723d5c..8590aba 100644 --- a/doc/src/declarative/anchor-layout.qdoc +++ b/doc/src/declarative/anchor-layout.qdoc @@ -14,7 +14,7 @@ Rectangle { id: rect1; ... } Rectangle { id: rect2; anchors.left: rect1.right; ... } \endcode -In this case, the left edge of \e rect2 is bound to the right edge of rect1, producing the following: +In this case, the left edge of \e rect2 is bound to the right edge of \e rect1, producing the following: \image edge1.png diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc index 1e00bd9..14bebb1 100644 --- a/doc/src/declarative/focus.qdoc +++ b/doc/src/declarative/focus.qdoc @@ -17,7 +17,7 @@ When the user presses or releases a key, the following occurs: \o The key event is delivered by the scene to the QML \l Item with \e {active focus}. If no \l Item has \e {active focus}, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues. \o If the QML \l Item with \e {active focus} accepts the key event, propagation stops. Otherwise the event is "bubbled up", by recursively passing it to each \l Item's parent until either the event is accepted, or the root \l Item is reached. -If the \c {Rect} element in the following example has active focus and the \e A key is pressed, it will bubble up to the \c {KeyActions}. However, pressing the \e B key will bubble up to the root item and thus subsequently be \l {QEvent::ignore()}{ignored}. +If the \c {Rectangle} element in the following example has active focus and the \e A key is pressed, it will bubble up to the \c {KeyActions}. However, pressing the \e B key will bubble up to the root item and thus subsequently be \l {QEvent::ignore()}{ignored}. \code Item { diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc index cfefdb9..56cc804 100644 --- a/doc/src/declarative/qmlintro.qdoc +++ b/doc/src/declarative/qmlintro.qdoc @@ -124,6 +124,7 @@ In the above example, the Text object will have normal opacity, since the line opacity: 0.5 has been turned into a comment. \section1 Properties +\target intro-properties \section2 Property naming diff --git a/doc/src/declarative/tutorial2.qdoc b/doc/src/declarative/tutorial2.qdoc index a076a62..66a0515 100644 --- a/doc/src/declarative/tutorial2.qdoc +++ b/doc/src/declarative/tutorial2.qdoc @@ -30,7 +30,7 @@ An \l Item is the most basic visual element in QML and is often used as a contai We declare a \c color property. This property is accessible from \e outside our component, this allows us to instantiate the cells with different colors. -This property is just an alias to an existing property - the color of the rectangle that compose the cell (see \l{Properties}). +This property is just an alias to an existing property - the color of the rectangle that compose the cell (see \l{intro-properties}{Properties}). \snippet examples/declarative/tutorials/helloworld/Cell.qml 5 -- cgit v0.12 From 72c3aefaa4c66d1cb6dcc99dadd808d921c9bfb7 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Thu, 8 Oct 2009 11:53:28 +1000 Subject: Rename preserveSelection to persistentSelection Task-number: QT-1113 --- src/declarative/QmlChanges.txt | 1 + src/declarative/fx/qfxtextedit.cpp | 14 +++++++------- src/declarative/fx/qfxtextedit.h | 6 +++--- src/declarative/fx/qfxtextedit_p.h | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index 7661e03..ee5acd4 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -41,6 +41,7 @@ Text elements: hAlign -> horizontalAlignment Text elements: vAlign -> verticalAlignment Text elements: highlightColor -> selectionColor Text elements: highlightedTextColor -> selectedTextColor +Text elements: preserveSelection -> persistentSelection State: operations -> changes Transition: operations -> animations Transition: fromState -> from diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index f4c2e4c..07444bb 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -407,7 +407,7 @@ void QFxTextEdit::setCursorVisible(bool on) return; d->cursorVisible = on; QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut); - if (!on && !d->preserveSelection) + if (!on && !d->persistentSelection) d->control->setCursorIsFocusIndicator(true); d->control->processEvent(&focusEvent, QPointF(0, 0)); } @@ -590,23 +590,23 @@ void QFxTextEdit::setFocusOnPress(bool on) } /*! - \qmlproperty bool TextEdit::preserveSelection + \qmlproperty bool TextEdit::persistentSelection Whether the TextEdit should keep the selection visible when it loses focus to another item in the scene. By default this is set to true; */ -bool QFxTextEdit::preserveSelection() const +bool QFxTextEdit::persistentSelection() const { Q_D(const QFxTextEdit); - return d->preserveSelection; + return d->persistentSelection; } -void QFxTextEdit::setPreserveSelection(bool on) +void QFxTextEdit::setPersistentSelection(bool on) { Q_D(QFxTextEdit); - if (d->preserveSelection == on) + if (d->persistentSelection == on) return; - d->preserveSelection = on; + d->persistentSelection = on; } qreal QFxTextEdit::textMargin() const diff --git a/src/declarative/fx/qfxtextedit.h b/src/declarative/fx/qfxtextedit.h index 1a5d968..f4f101a 100644 --- a/src/declarative/fx/qfxtextedit.h +++ b/src/declarative/fx/qfxtextedit.h @@ -83,7 +83,7 @@ class Q_DECLARATIVE_EXPORT QFxTextEdit : public QFxPaintedItem Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged) Q_PROPERTY(bool focusOnPress READ focusOnPress WRITE setFocusOnPress) - Q_PROPERTY(bool preserveSelection READ preserveSelection WRITE setPreserveSelection) + Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection) Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin) public: @@ -154,8 +154,8 @@ public: bool focusOnPress() const; void setFocusOnPress(bool on); - bool preserveSelection() const; - void setPreserveSelection(bool on); + bool persistentSelection() const; + void setPersistentSelection(bool on); qreal textMargin() const; void setTextMargin(qreal margin); diff --git a/src/declarative/fx/qfxtextedit_p.h b/src/declarative/fx/qfxtextedit_p.h index 9c73db9..82481ff 100644 --- a/src/declarative/fx/qfxtextedit_p.h +++ b/src/declarative/fx/qfxtextedit_p.h @@ -70,7 +70,7 @@ public: QFxTextEditPrivate() : color("black"), imgDirty(true), hAlign(QFxTextEdit::AlignLeft), vAlign(QFxTextEdit::AlignTop), dirty(false), wrap(false), richText(false), cursorVisible(false), focusOnPress(false), - preserveSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), + persistentSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QFxTextEdit::AutoText), document(0) { } @@ -98,7 +98,7 @@ public: bool richText; bool cursorVisible; bool focusOnPress; - bool preserveSelection; + bool persistentSelection; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; -- cgit v0.12 From 75da89f26a89ac1224372277799051f9224dbbe7 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 8 Oct 2009 12:43:29 +1000 Subject: Allow dial to be built as an exe. --- examples/declarative/dial/dial.pro | 9 +++++++++ examples/declarative/dial/dial.qrc | 10 ++++++++++ examples/declarative/dial/main.cpp | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 examples/declarative/dial/dial.pro create mode 100644 examples/declarative/dial/dial.qrc create mode 100644 examples/declarative/dial/main.cpp diff --git a/examples/declarative/dial/dial.pro b/examples/declarative/dial/dial.pro new file mode 100644 index 0000000..1d1f811 --- /dev/null +++ b/examples/declarative/dial/dial.pro @@ -0,0 +1,9 @@ +SOURCES = main.cpp +RESOURCES = dial.qrc + +QT += script declarative + +target.path = $$[QT_INSTALL_EXAMPLES]/declarative/dial +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS dial.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/declarative/dial +INSTALLS += target sources diff --git a/examples/declarative/dial/dial.qrc b/examples/declarative/dial/dial.qrc new file mode 100644 index 0000000..77354c0 --- /dev/null +++ b/examples/declarative/dial/dial.qrc @@ -0,0 +1,10 @@ + + + DialLibrary/background.png + DialLibrary/overlay.png + DialLibrary/needle_shadow.png + DialLibrary/needle.png + DialLibrary/Dial.qml + dial.qml + + diff --git a/examples/declarative/dial/main.cpp b/examples/declarative/dial/main.cpp new file mode 100644 index 0000000..b65c9ff --- /dev/null +++ b/examples/declarative/dial/main.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QmlView *canvas = new QmlView; + canvas->setUrl(QUrl("qrc:/dial.qml")); + canvas->execute(); + canvas->resize(210,240); + canvas->show(); + + return app.exec(); +} + + -- cgit v0.12 From 60a5afb67efcefa74cf452379dcef46b83daa265 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 7 Oct 2009 23:33:32 +1000 Subject: Self deleting binding test --- .../qmlecmascript/data/selfDeletingBinding.2.qml | 17 ++++++++++++++++ .../qmlecmascript/data/selfDeletingBinding.qml | 18 +++++++++++++++++ tests/auto/declarative/qmlecmascript/testtypes.h | 5 +++++ .../qmlecmascript/tst_qmlecmascript.cpp | 23 ++++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml create mode 100644 tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml new file mode 100644 index 0000000..58cf805 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml @@ -0,0 +1,17 @@ +import Qt.test 1.0 + +MyQmlContainer { + property bool triggerDelete: false + + children: [ + MyQmlObject { + // Will trigger deletion on binding assignment + deleteOnSet: Math.max(0, 1) + }, + + MyQmlObject { + // Will trigger deletion on binding assignment, but after component creation + deleteOnSet: if (triggerDelete) 1; else 0; + } + ] +} diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml new file mode 100644 index 0000000..074851a --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml @@ -0,0 +1,18 @@ +import Qt.test 1.0 + +MyQmlContainer { + property bool triggerDelete: false + + children: [ + MyQmlObject { + // Will trigger deletion during binding evaluation + stringProperty: {deleteMe(), "Hello"} + }, + + MyQmlObject { + // Will trigger deletion during binding evaluation, but after component creation + stringProperty: if (triggerDelete) { deleteMe(), "Hello" } else { "World" } + } + + ] +} diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h index ffc8fec..e6c2c20 100644 --- a/tests/auto/declarative/qmlecmascript/testtypes.h +++ b/tests/auto/declarative/qmlecmascript/testtypes.h @@ -23,6 +23,7 @@ class MyQmlObject : public QObject Q_OBJECT Q_ENUMS(MyEnum) Q_ENUMS(MyEnum2) + Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet); Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT) Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged) @@ -61,6 +62,9 @@ public: static MyQmlAttachedObject *qmlAttachedProperties(QObject *o) { return new MyQmlAttachedObject(o); } + + int deleteOnSet() const { return 1; } + void setDeleteOnSet(int v) { if(v) delete this; } signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); @@ -68,6 +72,7 @@ signals: void objectChanged(); public slots: + void deleteMe() { delete this; } void method() { m_methodCalled = true; } void method(int a) { if(a == 163) m_methodIntCalled = true; } void setString(const QString &s) { m_string = s; } diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 51f1ce7..6bc88c0 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -59,6 +59,7 @@ private slots: void dynamicCreation(); void dynamicDestruction(); void objectToString(); + void selfDeletingBinding(); private: QmlEngine engine; @@ -686,6 +687,28 @@ void tst_qmlecmascript::objectToString() QVERIFY(object->stringProperty().endsWith(", \"objName\")")); } +/* +Tests bindings that indirectly cause their own deletion work. + +This test is best run under valgrind to ensure no invalid memory access occur. +*/ +void tst_qmlecmascript::selfDeletingBinding() +{ + { + QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + object->setProperty("triggerDelete", true); + } + + { + QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + object->setProperty("triggerDelete", true); + } +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From 41ec742f6713f5b3b4da853f514d685c35c3f31f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 13:25:56 +1000 Subject: Make qmlecmascript:selfDeletingBinding pass Expressions and bindings must not reference data following their evalutation incase their object has been deleted. To solve this, the needed data is separated into a reference counted QmlExpressionData and QmlBindingData object. --- src/declarative/qml/qmlbinding.cpp | 59 ++++++----- src/declarative/qml/qmlbinding_p.h | 15 ++- src/declarative/qml/qmlexpression.cpp | 193 +++++++++++++++++++--------------- src/declarative/qml/qmlexpression_p.h | 48 +++++---- 4 files changed, 182 insertions(+), 133 deletions(-) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 454369b..3a34f46 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -57,11 +57,16 @@ QT_BEGIN_NAMESPACE QML_DEFINE_NOCREATE_TYPE(QmlBinding); -QmlBindingPrivate::QmlBindingPrivate() +QmlBindingData::QmlBindingData() : updating(false), enabled(false) { } +QmlBindingPrivate::QmlBindingPrivate() +: QmlExpressionPrivate(new QmlBindingData) +{ +} + QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) : QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) { @@ -81,7 +86,7 @@ QmlBinding::~QmlBinding() void QmlBinding::setTarget(const QmlMetaProperty &prop) { Q_D(QmlBinding); - d->property = prop; + d->bindingData()->property = prop; update(); } @@ -89,7 +94,7 @@ void QmlBinding::setTarget(const QmlMetaProperty &prop) QmlMetaProperty QmlBinding::property() const { Q_D(const QmlBinding); - return d->property; + return d->bindingData()->property; } void QmlBinding::update() @@ -99,45 +104,41 @@ void QmlBinding::update() #ifdef Q_ENABLE_PERFORMANCE_LOG QFxPerfTimer bu; #endif - if (!d->enabled) + QmlBindingData *data = d->bindingData(); + + if (!data->enabled) return; - if (!d->updating) { - d->updating = true; + data->addref(); - if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { + if (!data->updating) { + data->updating = true; - int idx = d->property.coreIndex(); + if (data->property.propertyCategory() == QmlMetaProperty::Bindable) { + + int idx = data->property.coreIndex(); Q_ASSERT(idx != -1); void *a[1]; QmlBinding *t = this; a[0] = (void *)&t; - QMetaObject::metacall(d->property.object(), + QMetaObject::metacall(data->property.object(), QMetaObject::WriteProperty, idx, a); } else { QVariant value = this->value(); - if (value.type() == QVariant::String) { - QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(d->property.propertyType()); - if (con) - value = con(value.toString()); - } - - if (d->property.propertyType() == QVariant::Vector3D && - value.type() == QVariant::String) { - value = qVariantFromValue(QmlStringConverters::vector3DFromString(value.toString())); - } - - d->property.write(value, QmlMetaProperty::Binding); + data->property.write(value, QmlMetaProperty::Binding); } - d->updating = false; + data->updating = false; } else { - qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name(); + qmlInfo(data->property.object()) << "Binding loop detected for property" + << data->property.name(); } + + data->release(); } void QmlBinding::valueChanged() @@ -148,30 +149,30 @@ void QmlBinding::valueChanged() void QmlBinding::setEnabled(bool e) { Q_D(QmlBinding); - d->enabled = e; + d->bindingData()->enabled = e; setTrackChange(e); + QmlAbstractBinding::setEnabled(e); + if (e) { - addToObject(d->property.object()); + addToObject(d->bindingData()->property.object()); update(); } else { removeFromObject(); } - - QmlAbstractBinding::setEnabled(e); } int QmlBinding::propertyIndex() { Q_D(QmlBinding); - return d->property.coreIndex(); + return d->bindingData()->property.coreIndex(); } bool QmlBinding::enabled() const { Q_D(const QmlBinding); - return d->enabled; + return d->bindingData()->enabled; } QString QmlBinding::expression() const diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h index 963e2c1..2c0c6b9 100644 --- a/src/declarative/qml/qmlbinding_p.h +++ b/src/declarative/qml/qmlbinding_p.h @@ -59,11 +59,10 @@ QT_BEGIN_NAMESPACE -class QmlBindingPrivate : public QmlExpressionPrivate +class QmlBindingData : public QmlExpressionData { - Q_DECLARE_PUBLIC(QmlBinding) public: - QmlBindingPrivate(); + QmlBindingData(); bool updating:1; bool enabled:1; @@ -71,6 +70,16 @@ public: QmlMetaProperty property; }; +class QmlBindingPrivate : public QmlExpressionPrivate +{ + Q_DECLARE_PUBLIC(QmlBinding) +public: + QmlBindingPrivate(); + + QmlBindingData *bindingData() { return static_cast(data); } + const QmlBindingData *bindingData() const { return static_cast(data); } +}; + QT_END_NAMESPACE #endif // QMLBINDING_P_H diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index e1c7afe..23e1700 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -51,41 +51,63 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE -QmlExpressionPrivate::QmlExpressionPrivate() +QmlExpressionData::QmlExpressionData() : expressionFunctionValid(false), expressionRewritten(false), me(0), trackChange(true), line(-1), guardList(0), guardListLength(0) { } +QmlExpressionData::~QmlExpressionData() +{ + if (guardList) { delete [] guardList; guardList = 0; } +} + +QmlExpressionPrivate::QmlExpressionPrivate() +: data(new QmlExpressionData) +{ + data->q = this; +} + +QmlExpressionPrivate::QmlExpressionPrivate(QmlExpressionData *d) +: data(d) +{ + data->q = this; +} + +QmlExpressionPrivate::~QmlExpressionPrivate() +{ + if (data) { data->q = 0; data->release(); data = 0; } +} + void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, QObject *me) { - expression = expr; + data->expression = expr; - QmlAbstractExpression::setContext(ctxt); - this->me = me; + data->QmlAbstractExpression::setContext(ctxt); + data->me = me; } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me) { - quint32 *data = (quint32 *)expr; - Q_ASSERT(*data == BasicScriptEngineData || - *data == PreTransformedQtScriptData); - if (*data == BasicScriptEngineData) { - sse.load((const char *)(data + 1), rc); + quint32 *exprData = (quint32 *)expr; + Q_ASSERT(*exprData == BasicScriptEngineData || + *exprData == PreTransformedQtScriptData); + if (*exprData == BasicScriptEngineData) { + data->sse.load((const char *)(exprData + 1), rc); } else { QmlCompiledData *dd = (QmlCompiledData *)rc; - expressionRewritten = true; - expression = QString::fromRawData((QChar *)(data + 3), data[2]); + data->expressionRewritten = true; + data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]); - int progIdx = *(data + 1); + int progIdx = *(exprData + 1); QmlEngine *engine = ctxt->engine(); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { - dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(expression)); + dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression)); } QmlContextPrivate *ctxtPriv = ctxt->d_func(); @@ -94,19 +116,14 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, if (me) scriptContext->pushScope(ep->objectClass->newQObject(me)); - expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); + data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); - expressionFunctionValid = true; + data->expressionFunctionValid = true; scriptEngine->popContext(); } - QmlAbstractExpression::setContext(ctxt); - this->me = me; -} - -QmlExpressionPrivate::~QmlExpressionPrivate() -{ - if (guardList) { delete [] guardList; guardList = 0; } + data->QmlAbstractExpression::setContext(ctxt); + data->me = me; } /*! @@ -173,7 +190,7 @@ QmlExpression::~QmlExpression() QmlEngine *QmlExpression::engine() const { Q_D(const QmlExpression); - return d->context()?d->context()->engine():0; + return d->data->context()?d->data->context()->engine():0; } /*! @@ -183,7 +200,7 @@ QmlEngine *QmlExpression::engine() const QmlContext *QmlExpression::context() const { Q_D(const QmlExpression); - return d->context(); + return d->data->context(); } /*! @@ -192,10 +209,10 @@ QmlContext *QmlExpression::context() const QString QmlExpression::expression() const { Q_D(const QmlExpression); - if (d->sse.isValid()) - return QLatin1String(d->sse.expression()); + if (d->data->sse.isValid()) + return QLatin1String(d->data->sse.expression()); else - return d->expression; + return d->data->expression; } /*! @@ -215,12 +232,12 @@ void QmlExpression::setExpression(const QString &expression) d->clearGuards(); - d->expression = expression; - d->expressionFunctionValid = false; - d->expressionRewritten = false; - d->expressionFunction = QScriptValue(); + d->data->expression = expression; + d->data->expressionFunctionValid = false; + d->data->expressionRewritten = false; + d->data->expressionFunction = QScriptValue(); - d->sse.clear(); + d->data->sse.clear(); } QVariant QmlExpressionPrivate::evalSSE() @@ -229,7 +246,7 @@ QVariant QmlExpressionPrivate::evalSSE() QFxPerfTimer perfsse; #endif - QVariant rv = sse.run(context(), me); + QVariant rv = data->sse.run(data->context(), data->me); return rv; } @@ -240,8 +257,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QFxPerfTimer perfqt; #endif - QmlContextPrivate *ctxtPriv = context()->d_func(); - QmlEngine *engine = context()->engine(); + QmlContextPrivate *ctxtPriv = data->context()->d_func(); + QmlEngine *engine = data->context()->engine(); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); if (secondaryScope) @@ -250,28 +267,29 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - if (!expressionFunctionValid) { + if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + if (data->me) + scriptContext->pushScope(ep->objectClass->newQObject(data->me)); - if (expressionRewritten) { - expressionFunction = scriptEngine->evaluate(expression, fileName, line); + if (data->expressionRewritten) { + data->expressionFunction = scriptEngine->evaluate(data->expression, + data->fileName, data->line); } else { QmlRewrite::RewriteBinding rewriteBinding; - const QString code = rewriteBinding(expression); - expressionFunction = scriptEngine->evaluate(code, fileName, line); + const QString code = rewriteBinding(data->expression); + data->expressionFunction = scriptEngine->evaluate(code, data->fileName, data->line); } scriptEngine->popContext(); - expressionFunctionValid = true; + data->expressionFunctionValid = true; } - QScriptValue svalue = expressionFunction.call(); + QScriptValue svalue = data->expressionFunction.call(); if (scriptEngine->hasUncaughtException()) { if (scriptEngine->uncaughtException().isError()){ @@ -329,7 +347,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope) Q_Q(QmlExpression); QVariant rv; - if (!q->engine() || (!sse.isValid() && expression.isEmpty())) + if (!q->engine() || (!data->sse.isValid() && data->expression.isEmpty())) return rv; #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -344,7 +362,11 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope) ep->currentExpression = q; - if (sse.isValid()) { + // This object might be deleted during the eval + QmlExpressionData *localData = data; + localData->addref(); + + if (data->sse.isValid()) { rv = evalSSE(); } else { rv = evalQtScript(secondaryScope); @@ -352,12 +374,17 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope) ep->currentExpression = lastCurrentExpression; - if ((!q->trackChange() || !ep->capturedProperties.count()) && guardList) { - clearGuards(); - } else if(q->trackChange()) { - updateGuards(ep->capturedProperties); + // Check if we were deleted + if (localData->q) { + if ((!data->trackChange || !ep->capturedProperties.count()) && data->guardList) { + clearGuards(); + } else if(data->trackChange) { + updateGuards(ep->capturedProperties); + } } + localData->release(); + lastCapturedProperties.copyAndClear(ep->capturedProperties); return rv; @@ -381,7 +408,7 @@ QVariant QmlExpression::value() bool QmlExpression::isConstant() const { Q_D(const QmlExpression); - return !d->guardList; + return !d->data->guardList; } /*! @@ -390,7 +417,7 @@ bool QmlExpression::isConstant() const bool QmlExpression::trackChange() const { Q_D(const QmlExpression); - return d->trackChange; + return d->data->trackChange; } /*! @@ -411,7 +438,7 @@ bool QmlExpression::trackChange() const void QmlExpression::setTrackChange(bool trackChange) { Q_D(QmlExpression); - d->trackChange = trackChange; + d->data->trackChange = trackChange; } /*! @@ -421,8 +448,8 @@ void QmlExpression::setTrackChange(bool trackChange) void QmlExpression::setSourceLocation(const QUrl &fileName, int line) { Q_D(QmlExpression); - d->fileName = fileName.toString(); - d->line = line; + d->data->fileName = fileName.toString(); + d->data->line = line; } /*! @@ -434,7 +461,7 @@ void QmlExpression::setSourceLocation(const QUrl &fileName, int line) QObject *QmlExpression::scopeObject() const { Q_D(const QmlExpression); - return d->me; + return d->data->me; } /*! \internal */ @@ -452,16 +479,16 @@ void QmlExpressionPrivate::clearGuards() notifyIdx = QmlExpression::staticMetaObject.indexOfMethod("__q_notify()"); - for (int ii = 0; ii < guardListLength; ++ii) { - if (guardList[ii].data()) { - QMetaObject::disconnect(guardList[ii].data(), - guardList[ii].notifyIndex, + for (int ii = 0; ii < data->guardListLength; ++ii) { + if (data->guardList[ii].data()) { + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, q, notifyIdx); } } - delete [] guardList; guardList = 0; - guardListLength = 0; + delete [] data->guardList; data->guardList = 0; + data->guardListLength = 0; } void QmlExpressionPrivate::updateGuards(const QPODVector &properties) @@ -474,10 +501,10 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorguardListLength) + newGuardList = new QmlExpressionData::SignalGuard[properties.count()]; bool outputWarningHeader = false; int hit = 0; @@ -485,20 +512,20 @@ void QmlExpressionPrivate::updateGuards(const QPODVector= guardListLength) { + if (ii >= data->guardListLength) { // New guard - } else if(guardList[ii].data() == property.object && - guardList[ii].notifyIndex == property.notifyIndex) { + } else if(data->guardList[ii].data() == property.object && + data->guardList[ii].notifyIndex == property.notifyIndex) { // Cache hit - if (!guardList[ii].isDuplicate || - (guardList[ii].isDuplicate && hit == ii)) { + if (!data->guardList[ii].isDuplicate || + (data->guardList[ii].isDuplicate && hit == ii)) { needGuard = false; ++hit; } - } else if(guardList[ii].data() && !guardList[ii].isDuplicate) { + } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { // Cache miss - QMetaObject::disconnect(guardList[ii].data(), - guardList[ii].notifyIndex, + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, q, notifyIdx); } /* else { @@ -507,9 +534,9 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorguardList[jj]; } if (property.notifyIndex != -1) { @@ -539,22 +566,22 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorguardList[ii]; } } - for (int ii = properties.count(); ii < guardListLength; ++ii) { - if (guardList[ii].data() && !guardList[ii].isDuplicate) { - QMetaObject::disconnect(guardList[ii].data(), - guardList[ii].notifyIndex, + for (int ii = properties.count(); ii < data->guardListLength; ++ii) { + if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { + QMetaObject::disconnect(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, q, notifyIdx); } } if (newGuardList) { - if (guardList) delete [] guardList; - guardList = newGuardList; - guardListLength = properties.count(); + if (data->guardList) delete [] data->guardList; + data->guardList = newGuardList; + data->guardListLength = properties.count(); } } diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 501e5d8..33016e6 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -79,23 +79,13 @@ private: QmlAbstractExpression *m_nextExpression; }; -class QmlExpression; -class QString; -class QmlExpressionPrivate : public QObjectPrivate, public QmlAbstractExpression +class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount { - Q_DECLARE_PUBLIC(QmlExpression) public: - QmlExpressionPrivate(); - ~QmlExpressionPrivate(); - - enum CompiledDataType { - BasicScriptEngineData = 1, - PreTransformedQtScriptData = 2 - }; + QmlExpressionData(); + ~QmlExpressionData(); - - void init(QmlContext *, const QString &, QObject *); - void init(QmlContext *, void *, QmlRefCount *, QObject *); + QmlExpressionPrivate *q; QString expression; bool expressionFunctionValid:1; @@ -109,10 +99,6 @@ public: QString fileName; int line; - QVariant value(QObject *secondaryScope = 0); - QVariant evalSSE(); - QVariant evalQtScript(QObject *secondaryScope); - struct SignalGuard : public QGuard { SignalGuard() : isDuplicate(false), notifyIndex(-1) {} @@ -132,6 +118,32 @@ public: }; SignalGuard *guardList; int guardListLength; +}; + +class QmlExpression; +class QString; +class QmlExpressionPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlExpression) +public: + QmlExpressionPrivate(); + QmlExpressionPrivate(QmlExpressionData *); + ~QmlExpressionPrivate(); + + enum CompiledDataType { + BasicScriptEngineData = 1, + PreTransformedQtScriptData = 2 + }; + + void init(QmlContext *, const QString &, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *); + + QmlExpressionData *data; + + QVariant value(QObject *secondaryScope = 0); + QVariant evalSSE(); + QVariant evalQtScript(QObject *secondaryScope); + void updateGuards(const QPODVector &properties); void clearGuards(); -- cgit v0.12 From 16cf54b2a1f8631c59950989691f6384c0550040 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 13:54:28 +1000 Subject: Tweak QScriptDeclarativeClass API to not be so silly --- src/script/bridge/qscriptdeclarativeclass.cpp | 42 +++++++++++++------------- src/script/bridge/qscriptdeclarativeclass_p.h | 3 +- src/script/bridge/qscriptdeclarativeobject.cpp | 14 +++++---- src/script/bridge/qscriptdeclarativeobject_p.h | 14 +++++++++ 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index a7667cb..d019839 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -76,17 +76,8 @@ QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentif return *this; } -class QScriptDeclarativeClassPrivate -{ -public: - QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0) {} - - QScriptEngine *engine; - QScriptDeclarativeClass *q_ptr; -}; - QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) -: context(0), d_ptr(new QScriptDeclarativeClassPrivate) +: d_ptr(new QScriptDeclarativeClassPrivate) { Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier)); d_ptr->q_ptr = this; @@ -178,8 +169,9 @@ QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Iden } /* -Returns the scope chain entry \a index from the end. This is equivalent to: - context->scopeChain().at(context->scopeChain.length() - 1 - index) +Returns the scope chain entry at \a index. If index is less than 0, returns +entries starting at the end. For example, scopeChainValue(context, -1) will return +the value last in the scope chain. */ QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index) { @@ -190,18 +182,21 @@ QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, i JSC::ScopeChainNode *node = frame->scopeChain(); JSC::ScopeChainIterator it(node); - int count = 0; - for (it = node->begin(); it != node->end(); ++it) - ++count; - - if (count < index) - return QScriptValue(); + if (index < 0) { + int count = 0; + for (it = node->begin(); it != node->end(); ++it) + ++count; - count -= index; + index = qAbs(index); + if (index > count) + return QScriptValue(); + else + index = count - index; + } for (it = node->begin(); it != node->end(); ++it) { - if (count == 0) { + if (index == 0) { JSC::JSObject *object = *it; if (!object) return QScriptValue(); @@ -214,7 +209,7 @@ QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, i return engine->scriptValueFromJSCValue(object); } else { - --count; + --index; } } @@ -314,3 +309,8 @@ QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok) return QVariant(); } +QScriptContext *QScriptDeclarativeClass::context() const +{ + return d_ptr->context; +} + diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 0d05ec5..b28209a 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -116,8 +116,9 @@ public: virtual QObject *toQObject(Object *, bool *ok = 0); virtual QVariant toVariant(Object *, bool *ok = 0); - QScriptContext *context; + QScriptContext *context() const; protected: + friend class QScriptDeclarativeClassPrivate; QScopedPointer d_ptr; }; diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index ffdebb0..76c2eb0 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -87,16 +87,17 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); - m_class->context = reinterpret_cast(exec); + QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class); + p->context = reinterpret_cast(exec); QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); if (flags & QScriptClass::HandlesReadAccess) { QScriptValue value = m_class->property(m_object, identifier); - m_class->context = 0; + p->context = 0; slot.setValue(engine->scriptValueToJSCValue(value)); return true; } - m_class->context = 0; + p->context = 0; return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); } @@ -108,15 +109,16 @@ void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); - m_class->context = reinterpret_cast(exec); + QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class); + p->context = reinterpret_cast(exec); QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesWriteAccess); if (flags & QScriptClass::HandlesWriteAccess) { m_class->setProperty(m_object, identifier, engine->scriptValueFromJSCValue(value)); - m_class->context = 0; + p->context = 0; return; } - m_class->context = 0; + p->context = 0; QScriptObjectDelegate::put(object, exec, propertyName, value, slot); } diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h index 9c14774..c6dfb83 100644 --- a/src/script/bridge/qscriptdeclarativeobject_p.h +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -63,6 +63,20 @@ QT_BEGIN_NAMESPACE class QScriptClass; +class QScriptDeclarativeClassPrivate +{ +public: + QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0) {} + + QScriptEngine *engine; + QScriptDeclarativeClass *q_ptr; + QScriptContext *context; + + static QScriptDeclarativeClassPrivate *get(QScriptDeclarativeClass *c) { + return c->d_ptr.data(); + } +}; + namespace QScript { -- cgit v0.12 From f5d0eed0973ff6e9054dfa2003d553117a5e272d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 13:54:42 +1000 Subject: Update to use new QScriptDeclarativeClass API --- src/declarative/qml/qmlobjectscriptclass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 9448dcc..84470fc 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -150,9 +150,9 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return rv; } - if (!evalContext && context) { + if (!evalContext && context()) { // Global object, QScriptContext activation object, QmlContext object - QScriptValue scopeNode = scopeChainValue(context, 3); + QScriptValue scopeNode = scopeChainValue(context(), -3); Q_ASSERT(scopeNode.isValid()); Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass); -- cgit v0.12 From 3215a23a399d881afafcf3cb9524124d452c669b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 13:55:24 +1000 Subject: Use correct file case --- src/declarative/qml/qmlmetatype.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 663e8e0..c40232f 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -948,9 +948,9 @@ QList QmlMetaType::qmlTypes() #include #include #include -#include -#include -#include +#include +#include +#include #include /*! -- cgit v0.12 From 28c8570d38fe1a5f57300a48668506a6235a9081 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 13:55:39 +1000 Subject: Fix relative-URLs of test scripts --- tools/qmlviewer/qfxtester.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qmlviewer/qfxtester.cpp b/tools/qmlviewer/qfxtester.cpp index a6a46eb..87ab43b 100644 --- a/tools/qmlviewer/qfxtester.cpp +++ b/tools/qmlviewer/qfxtester.cpp @@ -140,7 +140,8 @@ void QFxTester::run() void QFxTester::save() { QString filename = m_script + QLatin1String(".qml"); - QDir saveDir = QFileInfo(filename).absoluteDir(); + QFileInfo filenameInfo(filename); + QDir saveDir = filenameInfo.absoluteDir(); saveDir.mkpath("."); QFile file(filename); @@ -160,7 +161,7 @@ void QFxTester::save() if (!fe.hash.isEmpty()) { ts << " hash: \"" << fe.hash.toHex() << "\"\n"; } else if (!fe.image.isNull()) { - QString filename = m_script + "." + QString::number(imgCount++) + ".png"; + QString filename = filenameInfo.baseName() + "." + QString::number(imgCount++) + ".png"; fe.image.save(filename); ts << " image: \"" << filename << "\"\n"; } -- cgit v0.12 From f36619d24bc1a2b1e9bef6b4fac7d5d9a1916b7c Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 14:04:31 +1000 Subject: Fix (properly) test image saving. --- tools/qmlviewer/qfxtester.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qmlviewer/qfxtester.cpp b/tools/qmlviewer/qfxtester.cpp index 87ab43b..8005b0e 100644 --- a/tools/qmlviewer/qfxtester.cpp +++ b/tools/qmlviewer/qfxtester.cpp @@ -161,8 +161,9 @@ void QFxTester::save() if (!fe.hash.isEmpty()) { ts << " hash: \"" << fe.hash.toHex() << "\"\n"; } else if (!fe.image.isNull()) { - QString filename = filenameInfo.baseName() + "." + QString::number(imgCount++) + ".png"; - fe.image.save(filename); + QString filename = filenameInfo.baseName() + "." + QString::number(imgCount) + ".png"; + fe.image.save(m_script + "." + QString::number(imgCount) + ".png"); + imgCount++; ts << " image: \"" << filename << "\"\n"; } ts << " }\n"; -- cgit v0.12 From 0bb82245f83b47adf654d34d3e273dad1e39bd27 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 14:12:52 +1000 Subject: Call QApplication::exit() repeatedly This is necessary incase we want to exit before we've entered the event loop. --- tools/qmlviewer/qfxtester.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/qmlviewer/qfxtester.cpp b/tools/qmlviewer/qfxtester.cpp index 87ab43b..216685c 100644 --- a/tools/qmlviewer/qfxtester.cpp +++ b/tools/qmlviewer/qfxtester.cpp @@ -118,12 +118,14 @@ void QFxTester::imagefailure() void QFxTester::complete() { + if (options & QmlViewer::ExitOnComplete) + QApplication::exit(hasFailed?-1:0); + if (hasCompleted) return; hasCompleted = true; - if (options & QmlViewer::ExitOnComplete) - QApplication::exit(hasFailed?-1:0); - else if (options & QmlViewer::Play) + + if (options & QmlViewer::Play) qWarning("Script playback complete"); } -- cgit v0.12 From 87504046a111a4154349f6189ecc51ca85c48670 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 14:21:39 +1000 Subject: WebView auto sizing test. (image is just for doc, not in testscript) --- .../visual/qfxwebview/autosize/autosize.qml | 60 +++++++++++++++ .../visual/qfxwebview/autosize/data/autosize.0.png | Bin 0 -> 6886 bytes .../visual/qfxwebview/autosize/data/autosize.qml | 83 +++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 tests/auto/declarative/visual/qfxwebview/autosize/autosize.qml create mode 100644 tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.0.png create mode 100644 tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.qml diff --git a/tests/auto/declarative/visual/qfxwebview/autosize/autosize.qml b/tests/auto/declarative/visual/qfxwebview/autosize/autosize.qml new file mode 100644 index 0000000..74c6844 --- /dev/null +++ b/tests/auto/declarative/visual/qfxwebview/autosize/autosize.qml @@ -0,0 +1,60 @@ +import Qt 4.6 + +// The WebView size is determined by the width, height, +// preferredWidth, and preferredHeight properties. +Rectangle { + id: rect + color: "white" + width: 200 + height: layout.height + Column { + id: layout + spacing: 2 + WebView { + html: "No width defined." + Rectangle { color: "#10000000" + anchors.fill: parent + } + } + WebView { + width: rect.width + html: "The width is full." + Rectangle { + color: "#10000000" + anchors.fill: parent + } + } + WebView { + width: rect.width/2 + html: "The width is half." + Rectangle { + color: "#10000000" + anchors.fill: parent + } + } + WebView { + preferredWidth: rect.width/2 + html: "The preferredWidth is half." + Rectangle { + color: "#10000000" + anchors.fill: parent + } + } + WebView { + preferredWidth: rect.width/2 + html: "The_preferredWidth_is_half." + Rectangle { + color: "#10000000" + anchors.fill: parent + } + } + WebView { + width: rect.width/2 + html: "The_width_is_half." + Rectangle { + color: "#10000000" + anchors.fill: parent + } + } + } +} diff --git a/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.0.png b/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.0.png new file mode 100644 index 0000000..1f28b9a Binary files /dev/null and b/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.0.png differ diff --git a/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.qml b/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.qml new file mode 100644 index 0000000..47999be --- /dev/null +++ b/tests/auto/declarative/visual/qfxwebview/autosize/data/autosize.qml @@ -0,0 +1,83 @@ +import Qt.VisualTest 4.6 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 32 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 48 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 64 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 80 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 96 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 112 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 128 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 144 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 160 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 176 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 192 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 208 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 224 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 240 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 256 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 272 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 288 + hash: "66539e1b1983d95386b0d30d6e969904" + } + Frame { + msec: 304 + hash: "66539e1b1983d95386b0d30d6e969904" + } +} -- cgit v0.12 From d265b449325ef60624640f80f9438ac63547c1a8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 14:26:18 +1000 Subject: Fix crash --- src/declarative/qml/qmlobjectscriptclass.cpp | 2 +- .../qmlecmascript/data/extendedObjectPropertyLookup.qml | 8 ++++++++ .../auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 84470fc..d3a2a22 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -132,7 +132,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, cache = ddata->propertyCache; if (!cache) { cache = enginePrivate->cache(obj); - if (ddata) { cache->addref(); ddata->propertyCache = cache; } + if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; } } if (cache) { diff --git a/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml new file mode 100644 index 0000000..8ff3aeb --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 +import Qt 4.6 + +Object { + property MyExtendedObject a; + a: MyExtendedObject { id: Root } + property int b: Math.max(Root.extendedProperty, 0) +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 6bc88c0..dde3bb7 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -60,6 +60,7 @@ private slots: void dynamicDestruction(); void objectToString(); void selfDeletingBinding(); + void extendedObjectPropertyLookup(); private: QmlEngine engine; @@ -709,6 +710,20 @@ void tst_qmlecmascript::selfDeletingBinding() } } +/* +Test that extended object properties can be accessed. + +This test a regression where this used to crash. The issue was specificially +for extended objects that did not include a synthesized meta object (so non-root +and no synthesiszed properties). +*/ +void tst_qmlecmascript::extendedObjectPropertyLookup() +{ + QmlComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From f149107f3281fd537c98aaac5cba5934d55aa78a Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 8 Oct 2009 15:08:40 +1000 Subject: Clean up --- examples/declarative/animation/animation.qml | 8 ++ examples/declarative/connections/connections.qml | 11 +- examples/declarative/dynamic/dynamic.js | 26 ++-- examples/declarative/dynamic/dynamic.qml | 66 +++++++++-- examples/declarative/effects/test.qml | 73 +++++++----- examples/declarative/layouts/Button.qml | 27 ++++- examples/declarative/layouts/layouts.qml | 19 +-- examples/declarative/layouts/positioners.qml | 145 ++++++++++++++++++----- 8 files changed, 277 insertions(+), 98 deletions(-) diff --git a/examples/declarative/animation/animation.qml b/examples/declarative/animation/animation.qml index ccfe164..31c75e1 100644 --- a/examples/declarative/animation/animation.qml +++ b/examples/declarative/animation/animation.qml @@ -4,17 +4,20 @@ Rectangle { width: 400 height: 200 color: "white" + Rectangle { width: 40 height: 40 y: 80 color: "#FF0000" radius: 10 + // Animate the x property. Setting repeat to true makes the // animation repeat indefinitely, otherwise it would only run once. x: SequentialAnimation { running: true repeat: true + // Move from 0 to 360 in 500ms, using the easeInOutQuad easing function NumberAnimation { from: 0 @@ -22,10 +25,12 @@ Rectangle { easing: "easeInOutQuad" duration: 500 } + // Then pause for 200ms PauseAnimation { duration: 200 } + // Then move back to 0 in 2 seconds, using the easeInOutElastic easing function NumberAnimation { from: 360 @@ -34,16 +39,19 @@ Rectangle { duration: 2000 } } + // Alternate color between red and green color: SequentialAnimation { running: true repeat: true + ColorAnimation { property: "color" from: "#FF0000" to: "#00FF00" duration: 5000 } + ColorAnimation { property: "color" from: "#00FF00" diff --git a/examples/declarative/connections/connections.qml b/examples/declarative/connections/connections.qml index 521cc01..b693b7e 100644 --- a/examples/declarative/connections/connections.qml +++ b/examples/declarative/connections/connections.qml @@ -5,6 +5,7 @@ Rectangle { color: "blue" width: 40 height: 30 + Rectangle { id: dot color: "red" @@ -13,19 +14,19 @@ Rectangle { x: rect.width/2 y: rect.height/2 } + MouseRegion { id: mr anchors.fill: rect } + Connection { sender: mr signal: "clicked(mouse)" script: { - - color="green"; - dot.x = mouse.x-1; - dot.y = mouse.y-1; - + color = "green"; + dot.x = mouse.x-1; + dot.y = mouse.y-1; } } } diff --git a/examples/declarative/dynamic/dynamic.js b/examples/declarative/dynamic/dynamic.js index 8f1e138..8bfdba3 100644 --- a/examples/declarative/dynamic/dynamic.js +++ b/examples/declarative/dynamic/dynamic.js @@ -2,54 +2,56 @@ var dynamicObject = null; var fourthBox = null; var component = null; var started = false; + function createQml(p) { - return createQmlObject('DynRect {}',p,'DynPart.qml'); + return createQmlObject('DynRect {}', p, 'DynPart.qml'); } function destroyDynamicObject() { - if(!(dynamicObject==null)){ + if (!(dynamicObject == null)) { dynamicObject.destroy(); dynamicObject = null; } } function instantCreateWithComponent() {//Like create, but assumes instant readyness - if(dynamicObject!=null)//Already made + if (dynamicObject != null)//Already made return null; component = createComponent("dynamic.qml"); dynamicObject = component.createObject(); - if(dynamicObject == null){ + + if (dynamicObject == null) { print("error creating component"); - }else{ + } else { dynamicObject.parent = targetItem; return dynamicObject; } return null; } -function finishCreation(){ - if(component.isReady && dynamicObject == null){ +function finishCreation() { + if (component.isReady && dynamicObject == null) { dynamicObject = component.createObject(); dynamicObject.parent = targetItem; - }else if(component.isError){ + } else if (component.isError) { dynamicObject = null; print("error creating component"); print(component.errorsString()); } } -function createWithComponent(){ - if(component!=null){ +function createWithComponent() { + if (component != null) { return finishCreation(); } - if(started!=false){ + if (started != false) { finishCreation();//Remakes if destroyed return dynamicObject; } started = true; component = createComponent("dynamic.qml"); finishCreation(); - if(dynamicObject != null){ + if (dynamicObject != null) { return dynamicObject; } component.statusChanged.connect(finishCreation); diff --git a/examples/declarative/dynamic/dynamic.qml b/examples/declarative/dynamic/dynamic.qml index 6ea7ab8..66fdf87 100644 --- a/examples/declarative/dynamic/dynamic.qml +++ b/examples/declarative/dynamic/dynamic.qml @@ -1,22 +1,55 @@ import Qt 4.6 -Rectangle { id: page; width: 800; height: 800; color:"black" +Rectangle { + id: page + width: 800 + height: 800 + color: "black" Script { source: "dynamic.js" } - property bool extendStars: false; + + property bool extendStars: false + Item { id: targetItem; x: 100; y: 100; } Item { id: targetItem2; x: 0; y: 300; } - Rectangle { width: 100; height: 100; color: "green"; id: rect - MouseRegion { anchors.fill:parent; onClicked: {a = createWithComponent();}} + + Rectangle { + id: rect + width: 100 + height: 100 + color: "green" + + MouseRegion { + anchors.fill: parent + onClicked: { a = createWithComponent(); } + } } - Rectangle { width: 100; height: 100; color: "red"; id: rect2; y:100; - MouseRegion { anchors.fill:parent; onClicked: {destroyDynamicObject();}} + + Rectangle { + id: rect2 + width: 100 + height: 100 + y: 100 + color: "red" + + MouseRegion { + anchors.fill:parent + onClicked: { destroyDynamicObject(); } + } } - Rectangle { width: 100; height: 100; color: "blue"; id: rect3; y:200; - MouseRegion { anchors.fill:parent; onClicked: - { - if(fourthBox == null) { + + Rectangle { + id: rect3 + width: 100 + height: 100 + y: 200 + color: "blue" + + MouseRegion { + anchors.fill: parent + onClicked: { + if (fourthBox == null) { a = createQml(targetItem2); - if(a!=null) { + if (a != null) { a.parent = targetItem2;//BUG: this should happen automatically fourthBox = a; print(a.toStr()); @@ -31,5 +64,14 @@ Rectangle { id: page; width: 800; height: 800; color:"black" } } } - Particles { x:0; y:0; count:20; lifeSpan:500; width:100; height: if(extendStars){400;}else{300;} source:"star.png"} + + Particles { + x: 0 + y: 0 + count: 20 + lifeSpan: 500 + width: 100 + height: if (extendStars) { 400; } else { 300; } + source: "star.png" + } } diff --git a/examples/declarative/effects/test.qml b/examples/declarative/effects/test.qml index 83bfde2..73c6839 100644 --- a/examples/declarative/effects/test.qml +++ b/examples/declarative/effects/test.qml @@ -2,89 +2,108 @@ import Qt 4.6 Rectangle { color: "white" - width: 800 + width: 600 height: 600 Image { + id: blur source: "pic.jpg" effect: Blur { - blurRadius: NumberAnimation { id: blur; from: 0; to: 10; duration: 200; repeat: true } + blurRadius: NumberAnimation { + id: blurEffect + from: 0; to: 10 + duration: 200 + repeat: true + } } - MouseRegion { anchors.fill: parent; onClicked: blur.running = !blur.running } - - Text { color: "white"; text: "Blur" } + MouseRegion { anchors.fill: parent; onClicked: blurEffect.running = !blurEffect.running } } + Text { text: "Blur"; anchors.top: blur.bottom; anchors.horizontalCenter: blur.horizontalCenter } + Image { + id: grayscale source: "pic.jpg" - x: 200 - effect: Grayscale {} - Text { color: "white"; text: "Grayscale" } + effect: Grayscale {} } + Text { text: "Grayscale"; anchors.top: grayscale.bottom; anchors.horizontalCenter: grayscale.horizontalCenter } + Image { + id: colorize source: "pic.jpg" - x: 400 - effect: Colorize { color: "blue" } - Text { color: "white"; text: "Colorize" } + effect: Colorize { color: "blue" } } + Text { text: "Colorize"; anchors.top: colorize.bottom; anchors.horizontalCenter: colorize.horizontalCenter } + Image { + id: pixelize source: "pic.jpg" - y: 300 + effect: Pixelize { - pixelSize: NumberAnimation { id: pixelize; from: 0; to: 10; duration: 200; repeat: true } + pixelSize: NumberAnimation { + id: pixelizeEffect + from: 0; to: 10 + duration: 200 + repeat: true + } } - MouseRegion { anchors.fill: parent; onClicked: pixelize.running = !pixelize.running } - - Text { color: "white"; text: "Pixelize" } + MouseRegion { anchors.fill: parent; onClicked: pixelizeEffect.running = !pixelizeEffect.running } } + Text { text: "Pixelize"; anchors.top: pixelize.bottom; anchors.horizontalCenter: pixelize.horizontalCenter } Image { + id: dropShadow source: "pic.jpg" - x: 200 y: 300 + effect: DropShadow { blurRadius: 3 offset.x: 3 - offset.y: NumberAnimation { id: dropShadow; from: 0; to: 10; duration: 200; repeat: true; } + offset.y: NumberAnimation { id: dropShadowEffect; from: 0; to: 10; duration: 200; repeat: true; } } - MouseRegion { anchors.fill: parent; onClicked: dropShadow.running = !dropShadow.running } - - Text { color: "white"; text: "DropShadow" } + MouseRegion { anchors.fill: parent; onClicked: dropShadowEffect.running = !dropShadowEffect.running } } + Text { text: "Drop Shadow"; anchors.top: dropShadow.bottom; anchors.horizontalCenter: dropShadow.horizontalCenter } Image { + id: bloom source: "pic.jpg" - x: 400 y: 300 + effect: Bloom { blurRadius: 3 brightness: 128 - strength: NumberAnimation { id: bloom; from: 0; to: 1; duration: 200; repeat: true; } + strength: NumberAnimation { + id: bloomEffect + from: 0; to: 1 + duration: 200 + repeat: true + } } - MouseRegion { anchors.fill: parent; onClicked: bloom.running = !bloom.running } - - Text { color: "white"; text: "Bloom" } + MouseRegion { anchors.fill: parent; onClicked: bloomEffect.running = !bloomEffect.running } } + Text { text: "Bloom"; anchors.top: bloom.bottom; anchors.horizontalCenter: bloom.horizontalCenter } + Text { x: 100; y: 250 - text: "Clicking Blur, Pixelize or DropShadow will \ntoggle animation." + text: "Clicking Blur, Pixelize, Drop Shadow or Bloom will \ntoggle animation." color: "black" } diff --git a/examples/declarative/layouts/Button.qml b/examples/declarative/layouts/Button.qml index 6c2fd8d..186512b 100644 --- a/examples/declarative/layouts/Button.qml +++ b/examples/declarative/layouts/Button.qml @@ -1,20 +1,35 @@ import Qt 4.6 -Rectangle { border.color: "black"; color: "steelblue"; radius: 5; width: pix.width + text.width + 13; height: pix.height + 10; id: page +Rectangle { + id: page + border.color: "black" + color: "steelblue" + radius: 5 + width: pix.width + text.width + 13 + height: pix.height + 10 + property string text property string icon signal clicked + Image { id: pix; x: 5; y:5; source: parent.icon} + Text { id: text; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;} - MouseRegion{ id:mr; anchors.fill: parent; onClicked: {parent.focus = true; page.clicked()}} + + MouseRegion { + id: mr + anchors.fill: parent + onClicked: { parent.focus = true; page.clicked() } + } states: - State{ name:"pressed"; when:mr.pressed - PropertyChanges {target:text; x: 5} - PropertyChanges {target:pix; x:text.x+text.width + 3} + State { + name: "pressed"; when: mr.pressed + PropertyChanges { target:text; x: 5 } + PropertyChanges { target:pix; x:text.x+text.width + 3 } } transitions: Transition{ - NumberAnimation{ properties:"x,left"; easing:"easeInOutQuad"; duration:200 } + NumberAnimation { properties:"x,left"; easing:"easeInOutQuad"; duration:200 } } } diff --git a/examples/declarative/layouts/layouts.qml b/examples/declarative/layouts/layouts.qml index b54a7f3..accd969 100644 --- a/examples/declarative/layouts/layouts.qml +++ b/examples/declarative/layouts/layouts.qml @@ -1,20 +1,25 @@ import Qt 4.6 -Item { id: resizable - width:400; height:400; - GraphicsObjectContainer{ +Item { + id: resizable + width:400 + height:400 + + GraphicsObjectContainer { anchors.fill:parent - QGraphicsWidget{ + + QGraphicsWidget { size.width:parent.width size.height:parent.height - layout: QGraphicsLinearLayout{ - LayoutItem{ + + layout: QGraphicsLinearLayout { + LayoutItem { minimumSize: "100x100" maximumSize: "300x300" preferredSize: "100x100" Rectangle { color: "yellow"; anchors.fill: parent } } - LayoutItem{ + LayoutItem { minimumSize: "100x100" maximumSize: "400x400" preferredSize: "200x200" diff --git a/examples/declarative/layouts/positioners.qml b/examples/declarative/layouts/positioners.qml index fe28105..90efde2 100644 --- a/examples/declarative/layouts/positioners.qml +++ b/examples/declarative/layouts/positioners.qml @@ -1,43 +1,130 @@ import Qt 4.6 -Rectangle { width: 420; height: 420; id:page; color:"white" - Column { id: layout1; y:0; //width: 100; height:250; - move: Transition{ NumberAnimation {properties: "y"; easing: "easeOutBounce" }} - add: Transition{ NumberAnimation { properties: "y"; from: 500; duration:500; easing: "easeOutQuad"}} - remove: Transition { NumberAnimation { properties:"y"; to: 500; duration:500; easing: "easeInQuad"}} - Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } - Rectangle { id: blueV1; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15 - //opacity: Behavior{ NumberAnimation {}} + +Rectangle { + id: page + width: 420 + height: 420 + color: "white" + + Column { + id: layout1 + y: 0 + move: Transition { + NumberAnimation { + properties: "y"; easing: "easeOutBounce" + } } - Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 } - Rectangle { id: blueV2; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15 - //opacity: Behavior{ NumberAnimation {}} + add: Transition { + NumberAnimation { + properties: "y"; from: 500; duration:500; easing: "easeOutQuad" + } } + remove: Transition { + NumberAnimation { + properties:"y"; to: 500; duration:500; easing: "easeInQuad" + } + } + Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { id: blueV1; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { id: blueV2; color: "lightsteelblue"; width: 100; height: 50; border.color: "black"; radius: 15 } Rectangle { color: "orange"; width: 100; height: 50; border.color: "black"; radius: 15 } } - Row { id: layout2; y:300; - move: Transition{ NumberAnimation {properties: "x"; easing: "easeOutBounce" }} - add: Transition{ NumberAnimation { properties: "x"; from: 500; duration:500; easing: "easeOutQuad"} - NumberAnimation { properties: "opacity"; from: 0; duration: 500;}} - remove: Transition { NumberAnimation { properties: "x"; to: 500; duration:500; easing: "easeInQuad"} - NumberAnimation { properties: "opacity"; from: 1; duration: 500}} + + Row { + id: layout2 + y: 300 + move: Transition { + NumberAnimation { + properties: "x"; easing: "easeOutBounce" + } + } + add: Transition { + NumberAnimation { + properties: "x"; from: 500; duration:500; easing: "easeOutQuad" + } + NumberAnimation { + properties: "opacity"; from: 0; duration: 500; + } + } + remove: Transition { + NumberAnimation { + properties: "x"; to: 500; duration:500; easing: "easeInQuad" + } + NumberAnimation { + properties: "opacity"; from: 1; duration: 500 + } + } Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { id: blueH1; color: "lightsteelblue"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { id: blueH2; color: "lightsteelblue"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { color: "orange"; width: 50; height: 100; border.color: "black"; radius: 15 } } - Button { text: "Remove"; icon: "del.png"; x: 135; y:90; - onClicked: {blueH2.opacity=0; blueH1.opacity=0; blueV1.opacity=0; blueV2.opacity=0; blueG1.opacity=0; blueG2.opacity=0; blueG3.opacity=0;} - } - Button { text: "Add"; icon: "add.png"; x: 145; y:140; - onClicked: {blueH2.opacity=1; blueH1.opacity=1; blueV1.opacity=1; blueV2.opacity=1; blueG1.opacity=1; blueG2.opacity=1; blueG3.opacity=1;} - } - Grid { x:260; y:0; columns:3 - remove: Transition { NumberAnimation{ properties: "opacity"; from: 1; to: 0; duration: 500} - NumberAnimation{properties: "x,y"; easing: "easeOutBounce"} } - move: Transition { NumberAnimation{ properties: "x,y"; easing: "easeOutBounce" }} - add: Transition { NumberAnimation{ properties: "opacity"; from: 0; to: 1; duration: 500} - NumberAnimation{properties: "x,y"; easing: "easeOutBounce"} } + + Button { + text: "Remove" + icon: "del.png" + x: 135 + y: 90 + + onClicked: { + blueH2.opacity = 0 + blueH1.opacity = 0 + blueV1.opacity = 0 + blueV2.opacity = 0 + blueG1.opacity = 0 + blueG2.opacity = 0 + blueG3.opacity = 0 + } + } + + Button { + text: "Add" + icon: "add.png" + x: 145 + y: 140 + + onClicked: { + blueH2.opacity = 1 + blueH1.opacity = 1 + blueV1.opacity = 1 + blueV2.opacity = 1 + blueG1.opacity = 1 + blueG2.opacity = 1 + blueG3.opacity = 1 + } + } + + Grid { + x: 260 + y: 0 + columns: 3 + + remove: Transition { + NumberAnimation { + properties: "opacity"; from: 1; to: 0; duration: 500 + } + NumberAnimation { + properties: "x,y"; easing: "easeOutBounce" + } + } + + move: Transition { + NumberAnimation { + properties: "x,y"; easing: "easeOutBounce" + } + } + + add: Transition { + NumberAnimation { + properties: "opacity"; from: 0; to: 1; duration: 500 + } + NumberAnimation { + properties: "x,y"; easing: "easeOutBounce" + } + } + Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { id: blueG1; color: "lightsteelblue"; width: 50; height: 100; border.color: "black"; radius: 15 } Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 } -- cgit v0.12 From e795864872095d2179a3639403343ade3daf61c7 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 8 Oct 2009 15:09:39 +1000 Subject: Add command line options. --- tools/qmldebugger/main.cpp | 49 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/tools/qmldebugger/main.cpp b/tools/qmldebugger/main.cpp index 7fabfb7..ccd3761 100644 --- a/tools/qmldebugger/main.cpp +++ b/tools/qmldebugger/main.cpp @@ -23,9 +23,15 @@ Q_OBJECT public: Shell(QWidget * = 0); -private slots: + void setHost(const QString &host); + void setPort(quint16 port); + void showEngineTab(); + +public slots: void connectToHost(); void disconnectFromHost(); + +private slots: void connectionStateChanged(); private: @@ -38,6 +44,7 @@ private: QPushButton *m_disconnectButton; EnginePane *m_enginePane; + QTabWidget *m_tabs; }; Shell::Shell(QWidget *parent) @@ -71,19 +78,34 @@ Shell::Shell(QWidget *parent) m_disconnectButton->setEnabled(false); connectLayout->addWidget(m_disconnectButton); - QTabWidget *tabs = new QTabWidget(this); - layout->addWidget(tabs); + m_tabs = new QTabWidget(this); + layout->addWidget(m_tabs); CanvasFrameRate *cfr = new CanvasFrameRate(&client, this); - tabs->addTab(cfr, tr("Frame Rate")); + m_tabs->addTab(cfr, tr("Frame Rate")); m_enginePane = new EnginePane(&client, this); - tabs->addTab(m_enginePane, tr("QML Engine")); + m_tabs->addTab(m_enginePane, tr("QML Engine")); QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(connectionStateChanged())); connectionStateChanged(); } +void Shell::setHost(const QString &host) +{ + m_host->setText(host); +} + +void Shell::setPort(quint16 port) +{ + m_port->setValue(port); +} + +void Shell::showEngineTab() +{ + m_tabs->setCurrentWidget(m_enginePane); +} + void Shell::connectionStateChanged() { switch (client.state()) { @@ -132,9 +154,24 @@ int main(int argc, char ** argv) { QApplication app(argc, argv); + QStringList args = app.arguments(); + Shell shell; - shell.show(); + if (args.contains("--engine")) + shell.showEngineTab(); + + if (args.count() > 1 && args.at(1).contains(':')) { + QStringList hostAndPort = args.at(1).split(':'); + bool ok = false; + quint16 port = hostAndPort[1].toInt(&ok); + if (ok) { + shell.setHost(hostAndPort[0]); + shell.setPort(port); + shell.connectToHost(); + } + } + shell.show(); return app.exec(); } -- cgit v0.12 From 5525a2f1216b03b8a226d4c1d7817024f1010019 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 15:28:00 +1000 Subject: spel --- doc/src/declarative/advtutorial4.qdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/declarative/advtutorial4.qdoc b/doc/src/declarative/advtutorial4.qdoc index ae38c5e..332bf02 100644 --- a/doc/src/declarative/advtutorial4.qdoc +++ b/doc/src/declarative/advtutorial4.qdoc @@ -56,9 +56,9 @@ And now the game should be beautifully animated and smooth, with a subtle (or no \section2 Web-based High Scores -Another extension we might want for the game is some way of storing and retriveing high scores. In this tutorial we'll show you how to integrate a web enabled high score storage into your QML application. The implementation we've done is very simple - the high score data is posted to a php script running on a server somewhere, and that server then stores it and displays it to visitors. You could request an XML or QML file from that same server, which contained and displayed the scores, but that's beyond the scope of this tutorial. +Another extension we might want for the game is some way of storing and retrieving high scores. In this tutorial we'll show you how to integrate a web enabled high score storage into your QML application. The implementation we've done is very simple - the high score data is posted to a php script running on a server somewhere, and that server then stores it and displays it to visitors. You could request an XML or QML file from that same server, which contained and displayed the scores, but that's beyond the scope of this tutorial. -For better high score data, we want the name and time of the player. The time is obtained in the script fairly simply, but we have to ask the player for their name. We thus re-use the dialog QML file to pop up a dialog asking for the player's name (and if they exit this dialog without entering it they have a way to opt out of posting their high score). When the dialog is closed, if the player entered their name we can send the data to the web service in the followign snippet out of the script file: +For better high score data, we want the name and time of the player. The time is obtained in the script fairly simply, but we have to ask the player for their name. We thus re-use the dialog QML file to pop up a dialog asking for the player's name (and if they exit this dialog without entering it they have a way to opt out of posting their high score). When the dialog is closed, if the player entered their name we can send the data to the web service in the following snippet out of the script file: \snippet declarative/tutorials/samegame/samegame4/content/samegame.js 1 -- cgit v0.12 From ca6ec0bd63a8772ceaf947ca25258ef45f58fa60 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 8 Oct 2009 15:46:12 +1000 Subject: doc cleanup --- doc/src/declarative/advtutorial.qdoc | 48 ++++++++- doc/src/declarative/advtutorial1.qdoc | 56 +++++++++-- doc/src/declarative/advtutorial2.qdoc | 93 +++++++++++++++--- doc/src/declarative/advtutorial3.qdoc | 87 ++++++++++++++--- doc/src/declarative/advtutorial4.qdoc | 107 ++++++++++++++++++--- doc/src/declarative/anchor-layout.qdoc | 41 ++++++++ doc/src/declarative/animation.qdoc | 41 ++++++++ doc/src/declarative/basictypes.qdoc | 41 ++++++++ doc/src/declarative/binding.qdoc | 41 ++++++++ doc/src/declarative/cppitem.qdoc | 41 ++++++++ doc/src/declarative/elements.qdoc | 41 ++++++++ doc/src/declarative/examples.qdoc | 47 ++++++++- doc/src/declarative/focus.qdoc | 41 ++++++++ doc/src/declarative/measuring-performance.qdoc | 41 ++++++++ doc/src/declarative/modules.qdoc | 43 ++++++++- doc/src/declarative/qmlforcpp.qdoc | 41 ++++++++ doc/src/declarative/qmlformat.qdoc | 41 ++++++++ doc/src/declarative/qmlintro.qdoc | 41 ++++++++ doc/src/declarative/qmlmodels.qdoc | 43 ++++++++- doc/src/declarative/qmlreference.qdoc | 54 ++++++++++- doc/src/declarative/qtdeclarative.qdoc | 11 ++- doc/src/declarative/qtprogrammers.qdoc | 41 ++++++++ .../tutorials/samegame/samegame2/samegame.qml | 8 +- .../tutorials/samegame/samegame3/samegame.qml | 8 +- 24 files changed, 1023 insertions(+), 74 deletions(-) diff --git a/doc/src/declarative/advtutorial.qdoc b/doc/src/declarative/advtutorial.qdoc index c8075de..21eab92 100644 --- a/doc/src/declarative/advtutorial.qdoc +++ b/doc/src/declarative/advtutorial.qdoc @@ -1,10 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page advtutorial.html \title Advanced Tutorial -This tutorial goes step-by-step through creating a full application using just QML. It is assumed that you already know basic QML (such as from doing the simple tutorial) and the focus is on showing how to turn that knowledge into a complete and functioning application. +This tutorial goes step-by-step through creating a full application using just QML. +It is assumed that you already know basic QML (such as from doing the simple tutorial) and the focus is on showing +how to turn that knowledge into a complete and functioning application. -In this tutorial we recreate, step by step, the Same Game demo in $QTDIR/demos/declarative/samegame.qml. The results of the individual steps are in the $QTDIR/examples/declarative/tutorials/samegame directory. +In this tutorial we recreate, step by step, the Same Game demo in $QTDIR/demos/declarative/samegame.qml. +The results of the individual steps are in the $QTDIR/examples/declarative/tutorials/samegame directory. Tutorial chapters: diff --git a/doc/src/declarative/advtutorial1.qdoc b/doc/src/declarative/advtutorial1.qdoc index 48b32cd..44a9c42 100644 --- a/doc/src/declarative/advtutorial1.qdoc +++ b/doc/src/declarative/advtutorial1.qdoc @@ -1,7 +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 documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page advtutorial1.html \example declarative/tutorials/samegame/samegame1 -\title Advanced Tutorial 1 - Creating the Game canvas and block +\title Advanced Tutorial 1 - Creating the game canvas and block \target advtutorial1 The first step is to create the items in your application. In Same Game we have a main game screen and the blocks that populate it. @@ -14,11 +55,10 @@ Here is the QML code for the basic elements. The game window: This gives you a basic game window, with room for the game canvas. A new game button and room to display the score. The one thing you may not recognize here -is the SystemPalette item. This item provides access to the Qt system palette +is the \l SystemPalette item. This item provides access to the Qt system palette and is used to make the button look more like a system button (for exact native -feel you would use a QPushButton). Since we want a fully QML button, and the Fx -primitives don't include a button, we had to write our own. Below is the code -which we wrote to do this: +feel you would use a \l QPushButton). Since we want a fully QML button, and QML does +not include a button, we had to write our own. Below is the code which we wrote to do this: \snippet declarative/tutorials/samegame/samegame1/Button.qml 0 @@ -31,8 +71,10 @@ And here is a simple block: Since it doesn't do anything yet it's very simple, just an image. As the tutorial progresses and the block starts doing things the file will become -more than just an image. Note that we've set the image to be the size of the itm. This will be used later, when we dynamically create and size the block items the image will be scaled automatically to the correct size. - +more than just an image. Note that we've set the image to be the size of the itm. +This will be used later, when we dynamically create and size the block items the image will be scaled automatically +to the correct size. + You should be familiar with all that goes on in these files so far. This is a very basic start and doesn't move at all - next we will populate the game canvas with some blocks. diff --git a/doc/src/declarative/advtutorial2.qdoc b/doc/src/declarative/advtutorial2.qdoc index 2d2fe19..97cd744 100644 --- a/doc/src/declarative/advtutorial2.qdoc +++ b/doc/src/declarative/advtutorial2.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page advtutorial2.html \title Advanced Tutorial 2 - Populating the Game Canvas @@ -8,37 +49,59 @@ first thing to do is to generate all of the blocks. Now we need to dynamically generate all of these blocks, because you have a new, random set of blocks every time. As they are dynamically generated every time the new game button is clicked, as opposed to on startup, we will be dynamically generating the blocks -in the ECMA script, as opposed to using a Repeater. +in the ECMAScript, as opposed to using a \l Repeater. -This adds enough script to justify a new file, samegame.js, the intial version +This adds enough script to justify a new file, \c{samegame.js}, the intial version of which is shown below \snippet declarative/tutorials/samegame/samegame2/samegame.js 0 -The gist of this code is that we create the blocks dynamically, as many as will fit, and then store them in an array for future reference. The 'initBoard' function will be hooked up to the new game button soon, and should be fairly straight forward. - -The 'createBlock' function is a lot bigger, and I'll explain it block by block. -First we ensure that the component has been constructed. QML elements, including composite ones like the Block.qml that we've written, are never created directly in script. While there is a function to parse and create an arbitrary QML string, in the case where you are repeatedly creating the sme item you will want to use the createComponent function. createComponent is a built-in function in the declarative ECMAscript, and returns a component object. A component object prepares and stores a QML element (usually a composite element) for easy and efficient use. When the component is ready, you can create a new instance of the loaded QML with the createObject method. If the component is loaded remotely (over HTTP fro example) then you will have to wait for the component to finish loading before calling createObject. Since we don't wait here (the waiting is a syncronous, the component object has a signal to tell you when it's done) this code will only work if the block QML is a local file. - -As we aren't waiting for he component, the next block of code creates a game block with component.createObject. Since there could be an error in the QML file you are trying to load, success is not guaranteed. The first bit of error checkign code comes right after createObject(), to ensure that the object loaded correctly. If it did not load correctly the function returns false, but we don't have that hooked up to the main UI to indicate that something has gone wrong. Instead we print out error messages to the console, because an error here means an invalid QML file and should only happen while you are developing and testing the UI. - -Next we start to set up our dynamically created block. Because the Block.qml file is generic it needs to be placed in the main scene, and in the right place. This is why parent, x, y, width and height are set. We then store it in the board array for later use. - -Finally, we have some more error handling. You can only call createObject if the component has loaded. If it has not loaded, either it is still loading or there was an error loading (such as a missing file). Since we don't request remote files the problem is likely to be a missing or misplaced file. Again we print this to the console to aid debugging. +The gist of this code is that we create the blocks dynamically, as many as will fit, and then store them in an array for future reference. +The \c initBoard function will be hooked up to the new game button soon, and should be fairly straight forward. + +The \c createBlock function is a lot bigger, and I'll explain it block by block. +First we ensure that the component has been constructed. QML elements, including composite ones like the \c Block.qml +that we've written, are never created directly in script. While there is a function to parse and create an arbitrary QML string, +in the case where you are repeatedly creating the sme item you will want to use the \c createComponent function. \c createComponent is +a built-in function in the declarative ECMAScript, and returns a component object. +A component object prepares and stores a QML element (usually a composite element) for easy and efficient use. +When the component is ready, you can create a new instance of the loaded QML with the \c createObject method. +If the component is loaded remotely (over HTTP for example) then you will have to wait for the component to finish loading +before calling \c createObject. Since we don't wait here (the waiting is a syncronous, the component object has a signal to tell +you when it's done) this code will only work if the block QML is a local file. + +As we aren't waiting for he component, the next block of code creates a game block with \c{component.createObject}. +Since there could be an error in the QML file you are trying to load, success is not guaranteed. +The first bit of error checkign code comes right after \c{createObject()}, to ensure that the object loaded correctly. +If it did not load correctly the function returns false, but we don't have that hooked up to the main UI to indicate +that something has gone wrong. Instead we print out error messages to the console, because an error here means an invalid +QML file and should only happen while you are developing and testing the UI. + +Next we start to set up our dynamically created block. +Because the \c{Block.qml} file is generic it needs to be placed in the main scene, and in the right place. +This is why \c parent, \c x, \c y, \c width and \c height are set. We then store it in the board array for later use. + +Finally, we have some more error handling. You can only call \c{createObject} if the component has loaded. +If it has not loaded, either it is still loading or there was an error loading (such as a missing file). +Since we don't request remote files the problem is likely to be a missing or misplaced file. +Again we print this to the console to aid debugging. You now have the code to create a field of blocks dynamically, like below: \image declarative-adv-tutorial2.png -To hook this code up to the 'New Game' button, you alter it as below: +To hook this code up to the \e{New Game} button, you alter it as below: \snippet declarative/tutorials/samegame/samegame2/samegame.qml 1 -We have just replaced the 'onClicked: print("Implement me!")' with 'onClicked: initBoard()'. Note that in order to have the function available, you'll need to include the script in the main file, by adding a script element to it. +We have just replaced the \c{onClicked: print("Implement me!")} with \c{onClicked: initBoard()}. +Note that in order to have the function available, you'll need to include the script in the main file, +by adding a script element to it. \snippet declarative/tutorials/samegame/samegame2/samegame.qml 2 -With those two changes, and the script file, you are now dynamically creating a field of blocks you can play with. They don't do anything now though; the next chapter will add the game mechanics. +With those two changes, and the script file, you are now dynamically creating a field of blocks you can play with. +They don't do anything now though; the next chapter will add the game mechanics. [Previous: \l {advtutorial1}{Advanced Tutorial 1}] [\l {advtutorial.html}{Advanced Tutorial}] [Next: \l {advtutorial3}{Advanced Tutorial 3}] diff --git a/doc/src/declarative/advtutorial3.qdoc b/doc/src/declarative/advtutorial3.qdoc index 635054b..841e150 100644 --- a/doc/src/declarative/advtutorial3.qdoc +++ b/doc/src/declarative/advtutorial3.qdoc @@ -1,33 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page advtutorial3.html \title Advanced Tutorial 3 - Implementing the Game Logic \target advtutorial3 -To the initBoard function we added clearing the board before hand, so that clicking new game won't leave the previous game lying around in the background. To the createComponent function we have added setting the type of the block to a number between one and three - it's fundamental to the game logic that the blocks be different types if you want a fun game. +To the initBoard function we added clearing the board before hand, so that clicking new game won't leave the previous +game lying around in the background. To the createComponent function we have added setting the type of the block to a +number between one and three - it's fundamental to the game logic that the blocks be different types if you want a fun game. The main change was adding the following game logic functions: \list -\o function handleClick(x,y) -\o function floodFill(xIdx,yIdx,type) -\o function shuffleDown() -\o function victoryCheck() -\o function floodMoveCheck(xIdx, yIdx, type) +\o function \c{handleClick(x,y)} +\o function \c{floodFill(xIdx,yIdx,type)} +\o function \c{shuffleDown()} +\o function \c{victoryCheck()} +\o function \c{floodMoveCheck(xIdx, yIdx, type)} \endlist -As this is a tutorial about QML, not game design, these functions will not be discussed in detail. The game logic here was written in script, but it could have been written in C++ and had these functions exposed just as well (in fact, probably faster). The interfacing between these funcions and QML is of interest though. Of these functions, only handleClick and victoryCheck interface closely with the QML. Those functions are shown below (the rest are still in the code for this tutorial located at $QTDIR/examples/declarative/tutorials/samegame). +As this is a tutorial about QML, not game design, these functions will not be discussed in detail. The game logic here +was written in script, but it could have been written in C++ and had these functions exposed just as well (in fact, probably faster). +The interfacing between these funcions and QML is of interest though. Of these functions, only \c handleClick and \c victoryCheck +interface closely with the QML. Those functions are shown below (the rest are still in the code for this tutorial located at +\c{$QTDIR/examples/declarative/tutorials/samegame}). \snippet declarative/tutorials/samegame/samegame3/samegame.js 1 \snippet declarative/tutorials/samegame/samegame3/samegame.js 2 -You'll notice them referring to the 'gameCanvas' item. This is an item that has been added to the QML for easy interfacing. It is placed next to the background image and replaces the background as the item to create the blocks in. Its code is shown below: +You'll notice them referring to the \c gameCanvas item. This is an item that has been added to the QML for easy interfacing. +It is placed next to the background image and replaces the background as the item to create the blocks in. +Its code is shown below: \snippet declarative/tutorials/samegame/samegame3/samegame.qml 1 -This item is the exact size of the board, contains a score property, and a mouse region for input. The blocks are now created as its children, and its size is used as the noe determining board size. Since it needs to bind its size to a multiple of tileSize, tileSize needs to be moved into a QML property and out of the script file. It can still be accessed from the script. +This item is the exact size of the board, contains a score property, and a mouse region for input. +The blocks are now created as its children, and its size is used as the noe determining board size. +Since it needs to bind its size to a multiple of \c tileSize, \c tileSize needs to be moved into a QML property and out of the script file. +It can still be accessed from the script. -The mouse region simply calls handleClick(), which deals with the input events.Should those events cause the player to score, gameCanvas.score is updated. The score display text item has also been changed to bind its text property to gamecanvas.score. Note that if score was a global variable in the samegame.js file yo ucould not bind to it. You can only bind to QML properties. +The mouse region simply calls \c handleClick(), which deals with the input events. Should those events cause the player to score, +\c{gameCanvas.score} is updated. The score display text item has also been changed to bind its text property to \c{gamecanvas.score}. +Note that if score was a global variable in the \c{samegame.js} file yo ucould not bind to it. You can only bind to QML properties. -victoryCheck() mostly just updates score. But it also pops up a dialog saying 'Game Over' when the game is over. In this example we wanted a pure-QML, animated dialog, and since the Fx primitives set doesn't contain one, we wrote our own. Below is the code for the Dialog element, note how it's designed so as to be quite usable imperatively from within the script file: +\c victoryCheck() mostly just updates score. But it also pops up a dialog saying \e {Game Over} when the game is over. +In this example we wanted a pure-QML, animated dialog, and since QML doesn't contain one, we wrote our own. +Below is the code for the \c Dialog element, note how it's designed so as to be quite usable imperatively from within the script file: \snippet declarative/tutorials/samegame/samegame3/Dialog.qml 0 @@ -35,9 +91,10 @@ And this is how it's used in the main QML file: \snippet declarative/tutorials/samegame/samegame3/samegame.qml 2 -Combined with the line of code in victoryCheck, this causes a dialog to appear when the game is over, informing the user of that fact. +Combined with the line of code in \c victoryCheck, this causes a dialog to appear when the game is over, informing the user of that fact. -We now have a working game! The blocks can be clicked, the player can score, and the game can end (and then you start a new one). Below is a screenshot of what has been accomplished so far: +We now have a working game! The blocks can be clicked, the player can score, and the game can end (and then you start a new one). +Below is a screenshot of what has been accomplished so far: \image declarative-adv-tutorial3.png @@ -49,7 +106,9 @@ And the code for the block: \snippet declarative/tutorials/samegame/samegame3/Block.qml 0 -The game works, but it's a little boring right now. Where's the smooth animated transitions? Where's the high scores? If you were a QML expert you could have written these in for the first iteration, but in this tutorial they've been saved until the next chapter - where your application becomes alive! +The game works, but it's a little boring right now. Where's the smooth animated transitions? Where's the high scores? +If you were a QML expert you could have written these in for the first iteration, but in this tutorial they've been saved +until the next chapter - where your application becomes alive! [Previous: \l {advtutorial2}{Advanced Tutorial 2}] [\l {advtutorial.html}{Advanced Tutorial}] [Next: \l {advtutorial4}{Advanced Tutorial 4}] diff --git a/doc/src/declarative/advtutorial4.qdoc b/doc/src/declarative/advtutorial4.qdoc index 291d2f2..514c11a 100644 --- a/doc/src/declarative/advtutorial4.qdoc +++ b/doc/src/declarative/advtutorial4.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page advtutorial4.html \title Advanced Tutorial 4 - Finishing Touches @@ -5,11 +46,19 @@ Now we're going to do two things to liven the game up. Animate the blocks and add a web-based high score system. -If you compare the samegame3 directory with samegame4, you'll noticed that we've cleaned the directory structure up. We now have a lot of files, and so they've been split up into folders - the most notable one being a content folder which we've placed all the QML but the main file. +If you compare the \c samegame3 directory with \c samegame4, you'll noticed that we've cleaned the directory structure up. +We now have a lot of files, and so they've been split up into folders - the most notable one being a content folder +which we've placed all the QML but the main file. \section2 Animated Blocks -The most vital animations are that the blocks move fluidly around the board. QML has many tools for fluid behavior, and in this case we're going to use the Follow element. By having the script set targetX and targetY, instead of x and y directly, we can set the x and y of the block to a follow. SpringFollow is a property value source, which means that you can set a property to be one of these elements and it will automatically bind the property to the element's value. The SpringFollow's value follows another value over time, when the value it is tracking changes the SpringFollow's value will also change, but it will move smoothly there over time with a spring-like movement (based on the spring parameters specified). This is shown in the below snippet of code from Block.qml: +The most vital animations are that the blocks move fluidly around the board. QML has many tools for fluid behavior, +and in this case we're going to use the \l Follow element. By having the script set \c targetX and \c targetY, instead of \c x +and \c y directly, we can set the \c x and \c y of the block to a follow. \l SpringFollow is a property value source, which means +that you can set a property to be one of these elements and it will automatically bind the property to the element's value. +The SpringFollow's value follows another value over time, when the value it is tracking changes the SpringFollow's +value will also change, but it will move smoothly there over time with a spring-like movement (based on the spring +parameters specified). This is shown in the below snippet of code from \c Block.qml: \code property int targetX: 0 @@ -19,15 +68,25 @@ The most vital animations are that the blocks move fluidly around the board. QML y: SpringFollow { source: targetY; spring: 2; damping: 0.2 } \endcode -We also have to change the samegame.js code, so that wherever it was setting the x or y it now sets targetX and targetY (including when creating the block). This simple change is all you need to get spring moving blocks that no longer teleport around the board. If you try doing just this though, you'll notice that they now never jump from one point to another, even in the initialization! This gives an odd effect of having them all jump out of the corner (0,0) on start up. We'd rather that they fall down from the top in rows. To do this, we disable the x Follow (but not the y follow) and only enable it after we've set the x in the createBlock function. The above snippet now becomes: +We also have to change the \c{samegame.js} code, so that wherever it was setting the \c x or \c y it now sets \c targetX and \c targetY +(including when creating the block). This simple change is all you need to get spring moving blocks that no longer teleport +around the board. If you try doing just this though, you'll notice that they now never jump from one point to another, even +in the initialization! This gives an odd effect of having them all jump out of the corner (0,0) on start up. We'd rather +that they fall down from the top in rows. To do this, we disable the x Follow (but not the y follow) and only enable it after +we've set the \c x in the \c createBlock function. The above snippet now becomes: \snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 1 -The next-most vital animation is a smooth exit. For this animation, we'll use a Behavior element. A Behavior is also a property value source, and it is much like SpringFollow except that it doesn't model the behavior of a spring. You specify how a Behavior transitions using the standard animations. As we want the blocks to smoothly fade in and out we'll set a Behavior on the block image's opacity, like so: +The next-most vital animation is a smooth exit. For this animation, we'll use a \l Behavior element. A Behavior is also a property +value source, and it is much like SpringFollow except that it doesn't model the behavior of a spring. You specify how a Behavior +transitions using the standard animations. As we want the blocks to smoothly fade in and out we'll set a Behavior on the block +image's opacity, like so: \snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 2 -Note that the 'opacity: 0' makes it start out transparent. We could set the opacity in the script file when we create the blocks, but instead we use states (as this is useful for the next animation we'll implement). The below snippet is set on the root element of Block.qml: +Note that the \c{opacity: 0} makes it start out transparent. We could set the opacity in the script file when we create the blocks, +but instead we use states (as this is useful for the next animation we'll implement). The below snippet is set on the root +element of \c{Block.qml}: \code property bool dying: false states: [ @@ -39,34 +98,52 @@ Note that the 'opacity: 0' makes it start out transparent. We could set the opac ] \endcode -Now it will automatically fade in, as we set spawned to true already when implementing the block movement animations. To fade out, we set 'dying' to true instead of setting opacity to 0 when a block is destroyed (in the floodFill function). +Now it will automatically fade in, as we set spawned to true already when implementing the block movement animations. +To fade out, we set 'dying' to true instead of setting opacity to 0 when a block is destroyed (in the \c floodFill function). -The least vital animations are a cool-looking particle effect when they get destroyed. First we create a Particles Element in the block, like so: +The least vital animations are a cool-looking particle effect when they get destroyed. First we create a \l Particles element in +the block, like so: \snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 3 -To fully understand this you'll want to look at the Particles element documentation, but it's important to note that count is set to zero. -We next extend the 'dying' state, which triggers the particles by setting the count to non-zero. The code for the states now look like this: +To fully understand this you'll want to look at the Particles element documentation, but it's important to note that count is set +to zero. +We next extend the 'dying' state, which triggers the particles by setting the count to non-zero. The code for the states now look +like this: \snippet declarative/tutorials/samegame/samegame4/content/BoomBlock.qml 4 -And now the game should be beautifully animated and smooth, with a subtle (or not-so-subtle) animation added for all of the player's actions. The end result is shown below: +And now the game should be beautifully animated and smooth, with a subtle (or not-so-subtle) animation added for all of the +player's actions. The end result is shown below: \image declarative-adv-tutorial4.gif \section2 Web-based High Scores -Another extension we might want for the game is some way of storing and retriveing high scores. In this tutorial we'll show you how to integrate a web enabled high score storage into your QML application. The implementation we've done is very simple - the high score data is posted to a php script running on a server somewhere, and that server then stores it and displays it to visitors. You could request an XML or QML file from that same server, which contained and displayed the scores, but that's beyond the scope of this tutorial. +Another extension we might want for the game is some way of storing and retriveing high scores. In this tutorial we'll show you +how to integrate a web enabled high score storage into your QML application. The implementation we've done is very +simple - the high score data is posted to a php script running on a server somewhere, and that server then stores it and +displays it to visitors. You could request an XML or QML file from that same server, which contained and displayed the scores, +but that's beyond the scope of this tutorial. -For better high score data, we want the name and time of the player. The time is obtained in the script fairly simply, but we have to ask the player for their name. We thus re-use the dialog QML file to pop up a dialog asking for the player's name (and if they exit this dialog without entering it they have a way to opt out of posting their high score). When the dialog is closed, if the player entered their name we can send the data to the web service in the followign snippet out of the script file: +For better high score data, we want the name and time of the player. The time is obtained in the script fairly simply, but we +have to ask the player for their name. We thus re-use the dialog QML file to pop up a dialog asking for the player's name (and +if they exit this dialog without entering it they have a way to opt out of posting their high score). When the dialog is closed, +if the player entered their name we can send the data to the web service in the followign snippet out of the script file: \snippet declarative/tutorials/samegame/samegame4/content/samegame.js 1 -This is the same XMLHttpRequest() as you'll find in browser javascript, and can be used in the same way to dynamically get XML or QML from the web service to display the high scores. We don't worry about the response here though, we just post the high score data to the web server. If it had returned a QML file (or a URL to a QML file) you could instantiate it in much the same way as you did the blocks. +This is the same \c XMLHttpRequest() as you'll find in browser javascript, and can be used in the same way to dynamically get XML +or QML from the web service to display the high scores. We don't worry about the response here though, we just post the high +score data to the web server. If it had returned a QML file (or a URL to a QML file) you could instantiate it in much the same +way as you did the blocks. -An alternate way to access and submit web-based data would be to use QML elements designed for this purpose - XmlListModel makes it very easy to fetch and display XML based data such as RSS in a QML application (see the Flickr demo for an example). +An alternate way to access and submit web-based data would be to use QML elements designed for this purpose - XmlListModel +makes it very easy to fetch and display XML based data such as RSS in a QML application (see the Flickr demo for an example). -By following this tutorial you've now ben shown how to write a fully functional application in QML, with the application logic written in a script file and with both many fluid animations and being web-enabled. Congratulations, you should now be skilled enough to write your own QML applications. +By following this tutorial you've now ben shown how to write a fully functional application in QML, with the application logic +written in a script file and with both many fluid animations and being web-enabled. Congratulations, you should now be skilled +enough to write your own QML applications. [Previous: \l {advtutorial3}{Advanced Tutorial 3}] [\l {advtutorial.html}{Advanced Tutorial}] */ diff --git a/doc/src/declarative/anchor-layout.qdoc b/doc/src/declarative/anchor-layout.qdoc index 8590aba..503b881 100644 --- a/doc/src/declarative/anchor-layout.qdoc +++ b/doc/src/declarative/anchor-layout.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page anchor-layout.html \target anchor-layout diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc index 21263c1..caf78d3 100644 --- a/doc/src/declarative/animation.qdoc +++ b/doc/src/declarative/animation.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlanimation.html \target qmlanimation diff --git a/doc/src/declarative/basictypes.qdoc b/doc/src/declarative/basictypes.qdoc index 6feb91b..80ec211 100644 --- a/doc/src/declarative/basictypes.qdoc +++ b/doc/src/declarative/basictypes.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page basicqmltypes.html \title Common QML Types diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/binding.qdoc index 99f2853..4f9bdc8 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/binding.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page binding.html \title Data Binding in QML diff --git a/doc/src/declarative/cppitem.qdoc b/doc/src/declarative/cppitem.qdoc index 38da0fb..c5ef4c4 100644 --- a/doc/src/declarative/cppitem.qdoc +++ b/doc/src/declarative/cppitem.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page cppitem.html \target cppitem diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index 1fe4892..cb30a6e 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page elements.html \target elements diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc index 49a825a..5408098 100644 --- a/doc/src/declarative/examples.qdoc +++ b/doc/src/declarative/examples.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlexamples.html \target qmlexamples @@ -14,7 +55,11 @@ There are several illustrative QML examples available. From your build directory, \code - bin/qmlviewer $QT_SOURCE_DIR/demos/declarative/flickr/flickr.qml + bin/qmlviewer $QT_SOURCE_DIR/demos/declarative/flickr/flickr-desktop.qml +\endcode +or +\code + bin/qmlviewer $QT_SOURCE_DIR/demos/declarative/samegame/samegame.qml \endcode Many other simple examples can be found under the \c examples/declarative sub diff --git a/doc/src/declarative/focus.qdoc b/doc/src/declarative/focus.qdoc index 14bebb1..c92632b 100644 --- a/doc/src/declarative/focus.qdoc +++ b/doc/src/declarative/focus.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \target qmlfocus \page qmlfocus.html diff --git a/doc/src/declarative/measuring-performance.qdoc b/doc/src/declarative/measuring-performance.qdoc index 8c95422..01e7b03 100644 --- a/doc/src/declarative/measuring-performance.qdoc +++ b/doc/src/declarative/measuring-performance.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page optimizing-performance.html \target optimizing-performance diff --git a/doc/src/declarative/modules.qdoc b/doc/src/declarative/modules.qdoc index 7c67f60..3a6495d 100644 --- a/doc/src/declarative/modules.qdoc +++ b/doc/src/declarative/modules.qdoc @@ -1,4 +1,45 @@ -/*! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! \target qmlmodules \page qmlmodules.html \title Modules diff --git a/doc/src/declarative/qmlforcpp.qdoc b/doc/src/declarative/qmlforcpp.qdoc index 697ea59..5378571 100644 --- a/doc/src/declarative/qmlforcpp.qdoc +++ b/doc/src/declarative/qmlforcpp.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlforcpp.html \target qmlforcpp diff --git a/doc/src/declarative/qmlformat.qdoc b/doc/src/declarative/qmlformat.qdoc index 43eff05..be1afa4 100644 --- a/doc/src/declarative/qmlformat.qdoc +++ b/doc/src/declarative/qmlformat.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlformat.html \title QML Format Reference diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc index 56cc804..767cdd0 100644 --- a/doc/src/declarative/qmlintro.qdoc +++ b/doc/src/declarative/qmlintro.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlintroduction.html \title Introduction to the QML language diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc index 4712de1..eca81cd 100644 --- a/doc/src/declarative/qmlmodels.qdoc +++ b/doc/src/declarative/qmlmodels.qdoc @@ -1,4 +1,45 @@ -/*! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! \page qmlmodels.html \target qmlmodels \title Data Models diff --git a/doc/src/declarative/qmlreference.qdoc b/doc/src/declarative/qmlreference.qdoc index b26fc64..1498189 100644 --- a/doc/src/declarative/qmlreference.qdoc +++ b/doc/src/declarative/qmlreference.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page qmlreference.html \title QML Reference @@ -17,24 +58,27 @@ Getting Started: \list - \o \l {Introduction to the QML language} (in progress) - \o \l {tutorial}{Tutorial: 'Hello world!'} + \o \l {Introduction to the QML language} + \o \l {tutorial}{Tutorial: 'Hello World'} \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} + \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} \o \l {qmlexamples}{Examples} \endlist - Core Features: + Core QML Features: \list \o \l {binding}{Data Binding} - \o \l {anchor-layout}{Layout Anchors} + \o \l {qmlmodels}{Data Models} + \o \l {anchor-layout}{Anchor-based Layout} \o \l {qmlanimation}{Animation} - \o \l {components}{Components} \o \l {qmlmodules}{Modules} \o \l {qmlfocus}{Keyboard Focus} + \o \l {Extending types from QML} \endlist QML Reference: \list + \o \l {QML Format Reference} \o \l {elements}{QML Elements} \endlist */ diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index f94b9f8..1a13049 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -50,8 +50,8 @@ Qt Declarative is targetted at the sorts of user interface (and the sorts of hardware) in embedded devices such as phones, media players, and set-top boxes. It is also appropriate for highly custom desktop - user-interfaces, or special elements in more traditional desktop - user-interfaces. + user interfaces, or special elements in more traditional desktop + user interfaces. Building fluid applications is done declaratively, rather than procedurally. That is, you specify \e what the UI should look like and how it should behave @@ -62,10 +62,11 @@ Getting Started: \list - \o \l {qmlexamples}{Examples} + \o \l {Introduction to the QML language} \o \l {tutorial}{Tutorial: 'Hello World'} - \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} \o \l {tutorials-declarative-contacts.html}{Tutorial: 'Introduction to QML'} + \o \l {advtutorial.html}{Advanced Tutorial: 'Same Game'} + \o \l {qmlexamples}{Examples} \o \l {qmlforcpp}{QML For C++ Programmers} \endlist @@ -73,7 +74,7 @@ \list \o \l {binding}{Data Binding} \o \l {qmlmodels}{Data Models} - \o \l {anchor-layout}{Layout Anchors} + \o \l {anchor-layout}{Anchor-based Layout} \o \l {qmlanimation}{Animation} \o \l {qmlmodules}{Modules} \o \l {qmlfocus}{Keyboard Focus} diff --git a/doc/src/declarative/qtprogrammers.qdoc b/doc/src/declarative/qtprogrammers.qdoc index 3b20539..00c2d48 100644 --- a/doc/src/declarative/qtprogrammers.qdoc +++ b/doc/src/declarative/qtprogrammers.qdoc @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! INCOMPLETE diff --git a/examples/declarative/tutorials/samegame/samegame2/samegame.qml b/examples/declarative/tutorials/samegame/samegame2/samegame.qml index 78a3d83..63431b1 100644 --- a/examples/declarative/tutorials/samegame/samegame2/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame2/samegame.qml @@ -5,9 +5,9 @@ Rectangle { width: 490; height: 720 SystemPalette { id: activePalette; colorGroup: Qt.Active } - //![2] +//![2] Script { source: "samegame.js" } - //![2] +//![2] Item { width: parent.width; anchors.top: parent.top; anchors.bottom: ToolBar.top @@ -25,13 +25,13 @@ Rectangle { height: 32; width: parent.width anchors.bottom: Screen.bottom - //![1] +//![1] Button { id: btnA; text: "New Game"; onClicked: initBoard(); anchors.left: parent.left; anchors.leftMargin: 3 anchors.verticalCenter: parent.verticalCenter } - //![1] +//![1] Text { id: Score diff --git a/examples/declarative/tutorials/samegame/samegame3/samegame.qml b/examples/declarative/tutorials/samegame/samegame3/samegame.qml index a0883da..5b98f48 100644 --- a/examples/declarative/tutorials/samegame/samegame3/samegame.qml +++ b/examples/declarative/tutorials/samegame/samegame3/samegame.qml @@ -17,7 +17,7 @@ Rectangle { fillMode: "PreserveAspectCrop" } - //![1] +//![1] Item { id: gameCanvas property int score: 0 @@ -32,12 +32,12 @@ Rectangle { anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y); } } - //![1] +//![1] } - //![2] +//![2] Dialog { id: dialog; anchors.centerIn: parent; z: 21 } - //![2] +//![2] Rectangle { id: ToolBar -- cgit v0.12 From 15c31bb195d02e1bb489c1aff5f93f1cb829f51f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 16:05:02 +1000 Subject: Add url() for setUrl(). --- src/declarative/util/qmlview.cpp | 10 ++++++++++ src/declarative/util/qmlview.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/declarative/util/qmlview.cpp b/src/declarative/util/qmlview.cpp index f932e4a..14f8279 100644 --- a/src/declarative/util/qmlview.cpp +++ b/src/declarative/util/qmlview.cpp @@ -235,6 +235,16 @@ void QmlView::setUrl(const QUrl& url) } /*! + Returns the source URL, if set. + + \sa setUrl() + */ +QUrl QmlView::url() const +{ + return d->source; +} + +/*! Sets the source to the URL from the \a filename, and sets the QML string to \a qml. */ diff --git a/src/declarative/util/qmlview.h b/src/declarative/util/qmlview.h index b54101f..faf2564 100644 --- a/src/declarative/util/qmlview.h +++ b/src/declarative/util/qmlview.h @@ -70,6 +70,7 @@ public: virtual ~QmlView(); void setUrl(const QUrl&); + QUrl url() const; void setQml(const QString &qml, const QString &filename=QString()); QString qml() const; QmlEngine* engine(); -- cgit v0.12 From 75eba69aed3a9b73d29e91c1f5b5463654321bea Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Thu, 8 Oct 2009 16:05:07 +1000 Subject: make examples compile --- examples/webkit/fancybrowser/mainwindow.cpp | 2 +- examples/webkit/googlechat/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/webkit/fancybrowser/mainwindow.cpp b/examples/webkit/fancybrowser/mainwindow.cpp index 2adfa20..a3293b8 100644 --- a/examples/webkit/fancybrowser/mainwindow.cpp +++ b/examples/webkit/fancybrowser/mainwindow.cpp @@ -56,7 +56,7 @@ MainWindow::MainWindow() file.close(); //! [1] - QNetworkProxyFactory::setUseSystemConfigurationEnabled(true); + QNetworkProxyFactory::setUseSystemConfiguration(true); //! [2] view = new QWebView(this); diff --git a/examples/webkit/googlechat/main.cpp b/examples/webkit/googlechat/main.cpp index fd08114..6b5e11f 100644 --- a/examples/webkit/googlechat/main.cpp +++ b/examples/webkit/googlechat/main.cpp @@ -47,7 +47,7 @@ int main(int argc, char * argv[]) { QApplication app(argc, argv); - QNetworkProxyFactory::setUseSystemConfigurationEnabled(true); + QNetworkProxyFactory::setUseSystemConfiguration(true); GoogleChat *chat = new GoogleChat; chat->show(); -- cgit v0.12 From d3ccca2c493ea8149c93cb1f548a676d2d298939 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 16:05:29 +1000 Subject: Update. --- tests/auto/declarative/anchors/data/anchors.qml | 88 ++++++++++++------------ tests/auto/declarative/anchors/data/illegal1.qml | 6 +- tests/auto/declarative/anchors/data/illegal2.qml | 2 +- tests/auto/declarative/anchors/data/illegal3.qml | 6 +- tests/auto/declarative/anchors/data/loop1.qml | 2 +- tests/auto/declarative/anchors/data/loop2.qml | 2 +- tests/auto/declarative/anchors/tst_anchors.cpp | 36 ++++++---- 7 files changed, 77 insertions(+), 65 deletions(-) diff --git a/tests/auto/declarative/anchors/data/anchors.qml b/tests/auto/declarative/anchors/data/anchors.qml index 122d440..377dd2d 100644 --- a/tests/auto/declarative/anchors/data/anchors.qml +++ b/tests/auto/declarative/anchors/data/anchors.qml @@ -1,116 +1,116 @@ import Qt 4.6 -Rect { +Rectangle { color: "white" width: 240 height: 320 - Rect { id: MasterRect; x: 26; width: 96; height: 20; color: "red" } - Rect { - id: Rect1 + Rectangle { id: MasterRect; objectName: "MasterRect"; x: 26; width: 96; height: 20; color: "red" } + Rectangle { + id: Rect1; objectName: "Rect1" y: 20; width: 10; height: 10 anchors.left: MasterRect.left } - Rect { - id: Rect2 + Rectangle { + id: Rect2; objectName: "Rect2" y: 20; width: 10; height: 10 anchors.left: MasterRect.right } - Rect { - id: Rect3 + Rectangle { + id: Rect3; objectName: "Rect3" y: 20; width: 10; height: 10 anchors.left: MasterRect.horizontalCenter } - Rect { - id: Rect4 + Rectangle { + id: Rect4; objectName: "Rect4" y: 30; width: 10; height: 10 anchors.right: MasterRect.left } - Rect { - id: Rect5 + Rectangle { + id: Rect5; objectName: "Rect5" y: 30; width: 10; height: 10 anchors.right: MasterRect.right } - Rect { - id: Rect6 + Rectangle { + id: Rect6; objectName: "Rect6" y: 30; width: 10; height: 10 anchors.right: MasterRect.horizontalCenter } - Rect { - id: Rect7 + Rectangle { + id: Rect7; objectName: "Rect7" y: 50; width: 10; height: 10 anchors.left: parent.left } - Rect { - id: Rect8 + Rectangle { + id: Rect8; objectName: "Rect8" y: 50; width: 10; height: 10 anchors.left: parent.right } - Rect { - id: Rect9 + Rectangle { + id: Rect9; objectName: "Rect9" y: 50; width: 10; height: 10 anchors.left: parent.horizontalCenter } - Rect { - id: Rect10 + Rectangle { + id: Rect10; objectName: "Rect10" y: 60; width: 10; height: 10 anchors.right: parent.left } - Rect { - id: Rect11 + Rectangle { + id: Rect11; objectName: "Rect11" y: 60; width: 10; height: 10 anchors.right: parent.right } - Rect { - id: Rect12 + Rectangle { + id: Rect12; objectName: "Rect12" y: 60; width: 10; height: 10 anchors.right: parent.horizontalCenter } - Rect { - id: Rect13 + Rectangle { + id: Rect13; objectName: "Rect13" x: 200; width: 10; height: 10 anchors.top: MasterRect.bottom } - Rect { - id: Rect14 + Rectangle { + id: Rect14; objectName: "Rect14" width: 10; height: 10; color: "steelblue" anchors.verticalCenter: parent.verticalCenter } - Rect { - id: Rect15 + Rectangle { + id: Rect15; objectName: "Rect15" y: 200; height: 10 anchors.left: MasterRect.left anchors.right: MasterRect.right } - Rect { - id: Rect16 + Rectangle { + id: Rect16; objectName: "Rect16" y: 220; height: 10 anchors.left: MasterRect.left anchors.horizontalCenter: MasterRect.right } - Rect { - id: Rect17 + Rectangle { + id: Rect17; objectName: "Rect17" y: 240; height: 10 anchors.right: MasterRect.right anchors.horizontalCenter: MasterRect.left } - Rect { - id: Rect18 + Rectangle { + id: Rect18; objectName: "Rect18" x: 180; width: 10 anchors.top: MasterRect.bottom anchors.bottom: Rect12.top } - Rect { - id: Rect19 + Rectangle { + id: Rect19; objectName: "Rect19" y: 70; width: 10; height: 10 anchors.horizontalCenter: parent.horizontalCenter } - Rect { - id: Rect20 + Rectangle { + id: Rect20; objectName: "Rect20" y: 70; width: 10; height: 10 anchors.horizontalCenter: parent.right } - Rect { - id: Rect21 + Rectangle { + id: Rect21; objectName: "Rect21" y: 70; width: 10; height: 10 anchors.horizontalCenter: parent.left } diff --git a/tests/auto/declarative/anchors/data/illegal1.qml b/tests/auto/declarative/anchors/data/illegal1.qml index 1d23110..0a960d0 100644 --- a/tests/auto/declarative/anchors/data/illegal1.qml +++ b/tests/auto/declarative/anchors/data/illegal1.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: rect width: 120; height: 200; color: "white" - Rect { id: TheRect; width: 100; height: 100 } - Rect { + Rectangle { id: TheRect; width: 100; height: 100 } + Rectangle { anchors.left: TheRect.left anchors.right: TheRect.right anchors.horizontalCenter: TheRect.horizontalCenter diff --git a/tests/auto/declarative/anchors/data/illegal2.qml b/tests/auto/declarative/anchors/data/illegal2.qml index 9f81b91..2497738 100644 --- a/tests/auto/declarative/anchors/data/illegal2.qml +++ b/tests/auto/declarative/anchors/data/illegal2.qml @@ -1,6 +1,6 @@ import Qt 4.6 -Rect { +Rectangle { id: rect width: 120; height: 200; color: "white" Text { id: Text1; text: "Hello" } diff --git a/tests/auto/declarative/anchors/data/illegal3.qml b/tests/auto/declarative/anchors/data/illegal3.qml index 4f07456..27b2e4d 100644 --- a/tests/auto/declarative/anchors/data/illegal3.qml +++ b/tests/auto/declarative/anchors/data/illegal3.qml @@ -1,12 +1,12 @@ import Qt 4.6 -Rect { +Rectangle { id: rect width: 120; height: 200; color: "white" Item { - Rect { id: TheRect; width: 100; height: 100 } + Rectangle { id: TheRect; width: 100; height: 100 } } - Rect { + Rectangle { anchors.left: TheRect.left } } diff --git a/tests/auto/declarative/anchors/data/loop1.qml b/tests/auto/declarative/anchors/data/loop1.qml index adc5a10..ef6b63d 100644 --- a/tests/auto/declarative/anchors/data/loop1.qml +++ b/tests/auto/declarative/anchors/data/loop1.qml @@ -1,6 +1,6 @@ import Qt 4.6 -Rect { +Rectangle { id: rect width: 120; height: 200; color: "white" Text { id: Text1; anchors.right: Text2.right; text: "Hello" } diff --git a/tests/auto/declarative/anchors/data/loop2.qml b/tests/auto/declarative/anchors/data/loop2.qml index a6856f8..2445a15 100644 --- a/tests/auto/declarative/anchors/data/loop2.qml +++ b/tests/auto/declarative/anchors/data/loop2.qml @@ -1,6 +1,6 @@ import Qt 4.6 -Rect { +Rectangle { id: container; width: 600; height: 600; diff --git a/tests/auto/declarative/anchors/tst_anchors.cpp b/tests/auto/declarative/anchors/tst_anchors.cpp index a8b119c..38b7fe8 100644 --- a/tests/auto/declarative/anchors/tst_anchors.cpp +++ b/tests/auto/declarative/anchors/tst_anchors.cpp @@ -3,6 +3,8 @@ #include #include #include +#include + class tst_anchors : public QObject { @@ -28,14 +30,17 @@ template T *tst_anchors::findItem(QFxItem *parent, const QString &objectName) { const QMetaObject &mo = T::staticMetaObject; - for (int i = 0; i < parent->QSimpleCanvasItem::children().count(); ++i) { - QFxItem *item = qobject_cast(parent->QSimpleCanvasItem::children().at(i)); - if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) { - return static_cast(item); + QList children = parent->childItems(); + for (int i = 0; i < children.count(); ++i) { + QFxItem *item = qobject_cast(children.at(i)->toGraphicsObject()); + if (item) { + if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) { + return static_cast(item); + } + item = findItem(item, objectName); + if (item) + return static_cast(item); } - item = findItem(item, objectName); - if (item) - return static_cast(item); } return 0; @@ -97,7 +102,10 @@ void tst_anchors::loops() view->setUrl(QUrl("file://" SRCDIR "/data/loop1.qml")); - QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Possible anchor loop detected on horizontal anchor. "); //x5 + QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Possible anchor loop detected on horizontal anchor. "; + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); qApp->processEvents(); @@ -109,7 +117,8 @@ void tst_anchors::loops() view->setUrl(QUrl("file://" SRCDIR "/data/loop2.qml")); - QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Possible anchor loop detected on horizontal anchor. "); //x3 + QString expect = "QML QFxImage (" + view->url().toString() + ":14:3" + ") Possible anchor loop detected on horizontal anchor. "; + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); qApp->processEvents(); @@ -124,7 +133,8 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal1.qml")); - QTest::ignoreMessage(QtWarningMsg, "QML QFxRect (unknown location): Can't specify left, right, and hcenter anchors. "); + QString expect = "QML QFxRect (" + view->url().toString() + ":7:5" + ") Can't specify left, right, and hcenter anchors. "; + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); qApp->processEvents(); @@ -136,7 +146,8 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal2.qml")); - QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors. "); + QString expect = "QML QFxText (" + view->url().toString() + ":7:5" + ") Baseline anchor can't be used in conjunction with top, bottom, or vcenter anchors. "; + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); //qApp->processEvents(); @@ -148,7 +159,8 @@ void tst_anchors::illegalSets() view->setUrl(QUrl("file://" SRCDIR "/data/illegal3.qml")); - QTest::ignoreMessage(QtWarningMsg, "QML QFxRect (unknown location): Can't anchor to an item that isn't a parent or sibling. "); + QString expect = "QML QFxRect (" + view->url().toString() + ":9:5" + ") Can't anchor to an item that isn't a parent or sibling. "; + QTest::ignoreMessage(QtWarningMsg, expect.toLatin1()); view->execute(); //qApp->processEvents(); -- cgit v0.12 From 05e4f1eaeb3f916bcf845ae0d7e85d283e9ca1bd Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 8 Oct 2009 16:09:16 +1000 Subject: Remove redundant support/ files. --- examples/declarative/support/contact.cpp | 81 ------------- examples/declarative/support/contact.h | 140 ----------------------- examples/declarative/support/contactmodel.cpp | 158 -------------------------- examples/declarative/support/contactmodel.h | 55 --------- examples/declarative/support/support.pro | 12 -- 5 files changed, 446 deletions(-) delete mode 100644 examples/declarative/support/contact.cpp delete mode 100644 examples/declarative/support/contact.h delete mode 100644 examples/declarative/support/contactmodel.cpp delete mode 100644 examples/declarative/support/contactmodel.h delete mode 100644 examples/declarative/support/support.pro diff --git a/examples/declarative/support/contact.cpp b/examples/declarative/support/contact.cpp deleted file mode 100644 index 9ffeb97..0000000 --- a/examples/declarative/support/contact.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include "contact.h" - -QML_DEFINE_TYPE(0,0,0,0,Contact,Contact); -Contact::Contact() : QObject(0) -{ - m_firstName = "John"; - m_lastName = "Smith"; - m_portraitFile = "contact.png"; - m_company = "Trollkia"; - m_emails << "smith@trollkia.com" << "john45@gmail.com"; - - m_numbers << new PhoneNumber; - m_numbers << new PhoneNumber; - m_numbers << new PhoneNumber; - - m_numbers.at(0)->setType(PhoneNumber::HomePhone); - m_numbers.at(0)->setNumber("35412451"); - - m_numbers.at(1)->setType(PhoneNumber::BusinessPhone); - m_numbers.at(1)->setNumber("33424994"); - - m_numbers.at(2)->setType(PhoneNumber::MobilePhone); - m_numbers.at(2)->setNumber("0424655137"); - - m_addresses << new Address; - m_addresses << new Address; - m_addresses << new Address; - m_addresses.at(0)->setNumber(13); - m_addresses.at(0)->setStreet("Blackhill Cr"); - m_addresses.at(0)->setCountry("Australia"); - m_addresses.at(1)->setNumber(116); - m_addresses.at(1)->setStreet("Sandankerveien"); - m_addresses.at(1)->setCountry("Norway"); - m_addresses.at(2)->setNumber(92); - m_addresses.at(2)->setStreet("Elizibeth St"); - m_addresses.at(2)->setCountry("Australia"); -} - -void Contact::addNumber(PhoneNumber *newNumber) -{ - m_numbers << newNumber; - emit numbersChanged(); -} - -void Contact::addAddress(Address *newAddress) -{ - m_addresses << newAddress; - emit addressesChanged(); -} - -void Contact::addEmail(QString &newEmail) -{ - - m_emails << newEmail; - emit emailsChanged(); -} - -QML_DEFINE_TYPE(0,0,0,0,Address,Address); -Address::Address() -: _number(0) -{ -} - -QML_DEFINE_TYPE(0,0,0,0,PhoneNumber, PhoneNumber); -PhoneNumber::PhoneNumber() -: _type(HomePhone) -{ -} diff --git a/examples/declarative/support/contact.h b/examples/declarative/support/contact.h deleted file mode 100644 index 7b25869..0000000 --- a/examples/declarative/support/contact.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#ifndef CONTACT_H -#define CONTACT_H - -#include -#include - -class Address : public QObject -{ - Q_OBJECT -public: - Address(); - - Q_PROPERTY(int number READ number WRITE setNumber NOTIFY changed); - Q_PROPERTY(QString street READ street WRITE setStreet NOTIFY changed); - Q_PROPERTY(QString country READ country WRITE setCountry NOTIFY changed); - - int number() const { return _number; } - void setNumber(int n) { _number = n; emit changed(); } - - QString street() const { return _street; } - void setStreet(const QString &s) { _street = s; emit changed(); } - - QString country() const { return _country; } - void setCountry(const QString &c) { _country = c; emit changed(); } - -signals: - void changed(); - -private: - int _number; - QString _street; - QString _country; -}; -QML_DECLARE_TYPE(Address); - -class PhoneNumber : public QObject -{ - Q_OBJECT - Q_ENUMS(PhoneType) -public: - PhoneNumber(); - - enum PhoneType { - HomePhone, - BusinessPhone, - MobilePhone - }; - - Q_PROPERTY(QString number READ number WRITE setNumber NOTIFY changed); - Q_PROPERTY(PhoneType type READ type WRITE setType NOTIFY changed); - - QString number() const { return _number; } - void setNumber(QString n) { _number = n; emit changed(); } - - PhoneType type() const { return _type; } - void setType(PhoneType type) { _type = type; emit changed(); } - -signals: - void changed(); - -private: - QString _number; - PhoneType _type; -}; -QML_DECLARE_TYPE(PhoneNumber); - -class Contact : public QObject -{ - Q_OBJECT -public: - Contact(); - - Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY nameChanged); - QString firstName() const { return m_firstName; } - - Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY nameChanged); - QString lastName() const { return m_lastName; } - - Q_PROPERTY(QString portraitFile READ portraitFile WRITE setPortraitFile NOTIFY portraitChanged); - QString portraitFile() const { return m_portraitFile; } - - Q_PROPERTY(QString company READ company WRITE setCompany NOTIFY companyChanged); - QString company() const { return m_company; } - - Q_PROPERTY(QStringList emails READ emails WRITE setEmails NOTIFY emailsChanged); - QStringList emails() const { return m_emails; } - - Q_PROPERTY(QList
* addresses READ addresses); - QList
* addresses() { return &m_addresses; } - - Q_PROPERTY(QList* numbers READ numbers); - QList* numbers() { return &m_numbers; } - - - void addEmail(QString&); - void addAddress(Address*); - void addNumber(PhoneNumber*); - -public slots: - void setFirstName(const QString &name) { m_firstName = name; emit nameChanged(); } - void setLastName(const QString &name) { m_lastName = name; emit nameChanged(); } - void setPortraitFile(const QString &portraitFile) { m_portraitFile = portraitFile; emit portraitChanged(); } - void setCompany(const QString &company) { m_company = company; emit companyChanged(); } - void setEmails(const QStringList &emails) { m_emails = emails; emit emailsChanged(); } - -signals: - void nameChanged(); - void portraitChanged(); - void companyChanged(); - void emailsChanged(); - void numbersChanged(); - void addressesChanged(); - -private: - QString m_firstName; - QString m_lastName; - QString m_portraitFile; - - QString m_company; - - QList
m_addresses; - QListm_numbers; - QStringList m_emails; -}; -QML_DECLARE_TYPE(Contact); - -#endif diff --git a/examples/declarative/support/contactmodel.cpp b/examples/declarative/support/contactmodel.cpp deleted file mode 100644 index ff71b9c..0000000 --- a/examples/declarative/support/contactmodel.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include "contactmodel.h" - -ContactModel::ContactModel(QObject *parent) : QListModelInterface(parent) -{ - QFile f("../contacts/contacts.txt"); - f.open(QIODevice::ReadOnly); - QTextStream ts(&f); - QString text = ts.readLine(); - while(!text.isEmpty()) { - Contact *c = new Contact; - QStringList list = text.split(" "); - c->setFirstName(list[0]); - c->setLastName(list[1]); - for (int i = 2; i < list.count(); ++i) - c->addEmail(list[i]); - //contactList.append(c); - insertContact(c); - - text = ts.readLine(); - } - f.close(); -} - -ContactModel::~ContactModel() -{ - while (!contactList.isEmpty()) { - Contact *c = contactList.takeFirst(); - delete c; - } -} - -int ContactModel::count() const -{ - return contactList.count(); -} - -QHash ContactModel::data(int index, const QList &roles) const -{ - QHash returnHash; - - for (int i = 0; i < roles.size(); ++i) { - int role = roles.at(i); - QVariant info; - switch(role) { - case PortraitRole: - info = "contact.png"; - break; - case FirstNameRole: - info = contactList.at(index)->firstName(); - break; - case LastNameRole: - info = contactList.at(index)->lastName(); - break; - case CompanyRole: - info = contactList.at(index)->company(); - break; - case EmailsRole: - info = contactList.at(index)->emails(); - break; - case AddressesRole: - //returns QVariant BOOL - info = QVariant::fromValue(contactList.at(index)->addresses()); - break; - case NumbersRole: - info = QVariant::fromValue(contactList.at(index)->numbers()); - break; - default: - break; - } - returnHash.insert(role, info); - } - - return returnHash; -} - -QString ContactModel::toString(int role) const -{ - switch(role) { - case PortraitRole: - return "portrait"; - case FirstNameRole: - return "firstName"; - case LastNameRole: - return "lastName"; - case CompanyRole: - return "company"; - case EmailsRole: - return "emails"; - case AddressesRole: - return "addresses"; - case NumbersRole: - return "numbers"; - default: - return ""; - } -} - -QList ContactModel::roles() const -{ - return QList() << PortraitRole << FirstNameRole << LastNameRole << CompanyRole << EmailsRole << AddressesRole << NumbersRole; -} - -void ContactModel::deleteContact(int index) -{ - delete contactList.takeAt(index); - emit itemsRemoved(index, 1); -} - -int ContactModel::insertContact(Contact *contact) -{ - int index = 0; - QString fullName = contact->lastName(); - index = findIndex(fullName); - contactList.insert(index, contact); - emit itemsInserted(index, 1); - return index; -} - - -//search - binary search algorithm lastname only - -int ContactModel::findIndex(QString &searchName) const -{ - int start = 0; - int end = contactList.size()-1; - int middle = 0; - QString middleString; - - while (start <= end) - { - middle = (start+end)/2; - middleString = contactList.at(middle)->lastName(); - if (isAfter(searchName, middleString) < 0) start = middle+1; - else if( isAfter(middleString, searchName) < 0) end = middle-1; - else return middle; - } - return start; -} - -int ContactModel::isAfter(QString &name1, QString &name2) const -{ - //if c1 is after c2 alphabetically, return positive - int compString = QString::compare(name1, name2, Qt::CaseInsensitive); - return -compString; -} diff --git a/examples/declarative/support/contactmodel.h b/examples/declarative/support/contactmodel.h deleted file mode 100644 index e262358..0000000 --- a/examples/declarative/support/contactmodel.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#ifndef _CONTACTMODEL_H_ -#define _CONTACTMODEL_H_ - -#include -#include "contact.h" - -class ContactModel : public QListModelInterface -{ - Q_OBJECT -public: - ContactModel(QObject *parent = 0); - ~ContactModel(); - - enum Roles { - PortraitRole, - FirstNameRole, - LastNameRole, - CompanyRole, - EmailsRole, - AddressesRole, - NumbersRole - }; - - int count() const; - - QHash data(int index, const QList &roles) const; - QList roles() const; - - - QString toString(int role) const; - - void deleteContact(int index); - int insertContact(Contact *contact); - - int isAfter(QString &name1, QString &name2) const; - int findIndex(QString &searchName) const; - -private: - QList contactList; -}; - -#endif diff --git a/examples/declarative/support/support.pro b/examples/declarative/support/support.pro deleted file mode 100644 index 1da1a28..0000000 --- a/examples/declarative/support/support.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = lib -TARGET = QtFxSupport -DEPENDPATH += . -INCLUDEPATH += . -MOC_DIR = .moc -OBJECTS_DIR = .obj -DESTDIR = ../../lib -QT += script declarative - -HEADERS += contact.h contactmodel.h -SOURCES += contact.cpp contactmodel.cpp - -- cgit v0.12 From 115232074a4becd5cf03974ac351331de1217f7d Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 16:51:38 +1000 Subject: Remove spurious errors. Others seem real. --- tests/auto/declarative/listview/data/listview.qml | 2 +- tests/auto/declarative/listview/tst_listview.cpp | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/auto/declarative/listview/data/listview.qml b/tests/auto/declarative/listview/data/listview.qml index 1a241eb..5083329 100644 --- a/tests/auto/declarative/listview/data/listview.qml +++ b/tests/auto/declarative/listview/data/listview.qml @@ -7,7 +7,7 @@ Rectangle { resources: [ Component { id: Delegate - Item { + Rectangle { id: wrapper objectName: "wrapper" height: 20 diff --git a/tests/auto/declarative/listview/tst_listview.cpp b/tests/auto/declarative/listview/tst_listview.cpp index 19d324d..2a5fa1c 100644 --- a/tests/auto/declarative/listview/tst_listview.cpp +++ b/tests/auto/declarative/listview/tst_listview.cpp @@ -33,7 +33,7 @@ private: template void removed(); QmlView *createView(const QString &filename); template - T *findItem(QFxItem *parent, const QString &id, int index=0); + T *findItem(QFxItem *parent, const QString &id, int index=-1); }; class TestModel : public QListModelInterface @@ -188,7 +188,7 @@ void tst_QFxListView::items() QFxItem *viewport = listview->viewport(); QVERIFY(viewport != 0); - QCOMPARE(viewport->childItems().count(), model.count()); // assumes all are visible + QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item for (int i = 0; i < model.count(); ++i) { QFxText *name = findItem(viewport, "textName", i); @@ -262,7 +262,7 @@ void tst_QFxListView::inserted() // let transitions settle. QTest::qWait(1000); - QCOMPARE(viewport->childItems().count(), model.count()); // assumes all are visible + QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item QFxText *name = findItem(viewport, "textName", 1); QVERIFY(name != 0); @@ -282,7 +282,7 @@ void tst_QFxListView::inserted() // let transitions settle. QTest::qWait(1000); - QCOMPARE(viewport->childItems().count(), model.count()); // assumes all are visible + QCOMPARE(viewport->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item name = findItem(viewport, "textName", 0); QVERIFY(name != 0); @@ -338,6 +338,8 @@ void tst_QFxListView::removed() // Confirm items positioned correctly for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { QFxItem *item = findItem(viewport, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); QVERIFY(item->y() == i*20); } @@ -357,6 +359,8 @@ void tst_QFxListView::removed() // Confirm items positioned correctly for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { QFxItem *item = findItem(viewport, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); QCOMPARE(item->y(),i*20.0 + 20.0); } @@ -368,6 +372,8 @@ void tst_QFxListView::removed() // Confirm items positioned correctly for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { QFxItem *item = findItem(viewport, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); QCOMPARE(item->y(),i*20.0+20.0); } @@ -382,6 +388,8 @@ void tst_QFxListView::removed() // Confirm items positioned correctly for (int i = 2; i < 18; ++i) { QFxItem *item = findItem(viewport, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); QCOMPARE(item->y(),40+i*20.0); } @@ -392,6 +400,8 @@ void tst_QFxListView::removed() // Confirm items positioned correctly for (int i = 0; i < model.count() && i < viewport->childItems().count(); ++i) { QFxItem *item = findItem(viewport, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); QCOMPARE(item->y(),40+i*20.0); } @@ -452,7 +462,7 @@ QmlView *tst_QFxListView::createView(const QString &filename) } /* - Find an item with the specified id. If index is supplied then the + Find an item with the specified objectName. If index is supplied then the item must also evaluate the {index} expression equal to index */ template -- cgit v0.12 From 37d527f90a0ea430b4f97dd36a2048c89034ff97 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:02:47 +1000 Subject: Update NumberFormatter now only goes from number to (formatted) text. --- .../numberformatter/tst_numberformatter.cpp | 49 +--------------------- 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp index 78ec347..412557f 100644 --- a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp +++ b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp @@ -18,15 +18,11 @@ public: void cleanupTestCase() {} private slots: - void number_data(); - void number(); - void text_data(); void text(); private: QStringList strings; - QList numbers; QStringList formats; QStringList texts; }; @@ -43,16 +39,6 @@ tst_numberformat::tst_numberformat() << "1.0" << "1.01"; - numbers << 100 - << 12345 - << 1234567 - << 0.123 - << 0.9999 - << 0.989 - << 1 - << 1.0 - << 1.01; - formats << "" << "0000" << "0000.00" @@ -151,37 +137,6 @@ tst_numberformat::tst_numberformat() << "texts.size()" << texts.size(); } -void tst_numberformat::number_data() -{ - QTest::addColumn("string"); - QTest::addColumn("number"); - - for (int i = 0; i < strings.size(); i++) - QTest::newRow(QString::number(i).toAscii()) << strings.at(i) << numbers.at(i); -} - -void tst_numberformat::number() -{ - // ### tests the conversion from string to float - QFETCH(QString, string); - QFETCH(float, number); - - QString componentStr = QString("import Qt 4.6\nNumberFormatter { number: \"") + string + QString("\" }"); - - QmlEngine engine; - QmlComponent formatterComponent(&engine, componentStr.toAscii(), QUrl("file://")); - if(formatterComponent.isError()) - qDebug() << formatterComponent.errors(); - QVERIFY(formatterComponent.isReady()); - QmlNumberFormatter *formatter = qobject_cast(formatterComponent.create()); - QVERIFY(formatterComponent.isReady()); - QVERIFY(formatter != 0); - QCOMPARE((float)formatter->number(), number); - //qDebug() << formatter->format() << formatter->text(); - QVERIFY(formatter->format().isEmpty()); - QVERIFY(formatter->text() == QString("%1").arg(number, -1, 'f', -1)); -} - void tst_numberformat::text_data() { QTest::addColumn("string"); @@ -205,10 +160,10 @@ void tst_numberformat::text() QFETCH(QString, format); QFETCH(QString, text); - QString componentStr = QString("import Qt 4.6\nNumberFormatter { number: \"") + string + QString("\"; format: \"") + format + QString("\" }"); + QString componentStr = QString("import Qt 4.6\nNumberFormatter { number: ") + string + QString("; format: \"") + format + QString("\" }"); QmlEngine engine; - QmlComponent formatterComponent(&engine, componentStr.toAscii(), QUrl("file://")); + QmlComponent formatterComponent(&engine, componentStr.toAscii(), QUrl("file:///")); if(formatterComponent.isError()) qDebug() << formatterComponent.errors(); QVERIFY(formatterComponent.isReady()); -- cgit v0.12 From 63e652ca7ec3b6983ebc8b0edd10199da862d53c Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:13:23 +1000 Subject: Quieten expect net error --- .../declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp b/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp index 4d3ad55..5e24831 100644 --- a/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp +++ b/tests/auto/declarative/qfxpixmapcache/tst_qfxpixmapcache.cpp @@ -65,12 +65,13 @@ void tst_qfxpixmapcache::single_data() QTest::addColumn("target"); QTest::addColumn("incache"); QTest::addColumn("exists"); + QTest::addColumn("neterror"); // File URLs are optimized - QTest::newRow("local") << thisfile.resolved(QUrl("data/exists.png")) << localfile_optimized << true; - QTest::newRow("local") << thisfile.resolved(QUrl("data/notexists.png")) << localfile_optimized << false; - QTest::newRow("remote") << QUrl("http://qt.nokia.com/logo.png") << false << true; - QTest::newRow("remote") << QUrl("http://qt.nokia.com/thereisnologo.png") << false << false; + QTest::newRow("local") << thisfile.resolved(QUrl("data/exists.png")) << localfile_optimized << true << false; + QTest::newRow("local") << thisfile.resolved(QUrl("data/notexists.png")) << localfile_optimized << false << false; + QTest::newRow("remote") << QUrl("http://qt.nokia.com/logo.png") << false << true << false; + QTest::newRow("remote") << QUrl("http://qt.nokia.com/thereisnologo.png") << false << false << true; } void tst_qfxpixmapcache::single() @@ -78,6 +79,14 @@ void tst_qfxpixmapcache::single() QFETCH(QUrl, target); QFETCH(bool, incache); QFETCH(bool, exists); + QFETCH(bool, neterror); + + if (neterror) { + QString expected = "Network error loading QUrl( \"" + +target.toString()+"\" ) \"Error downloading " + +target.toString()+" - server replied: Not Found\" "; + QTest::ignoreMessage(QtWarningMsg, expected.toLatin1()); + } QPixmap pixmap; QVERIFY(pixmap.width() <= 0); // Check Qt assumption -- cgit v0.12 From 5ca691eb57133cef3144967a70faa41147a8a37f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:15:48 +1000 Subject: Follow -> SpringFollow --- tests/auto/declarative/qmldom/tst_qmldom.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/qmldom/tst_qmldom.cpp b/tests/auto/declarative/qmldom/tst_qmldom.cpp index e1419cc..77c13c3 100644 --- a/tests/auto/declarative/qmldom/tst_qmldom.cpp +++ b/tests/auto/declarative/qmldom/tst_qmldom.cpp @@ -119,7 +119,7 @@ void tst_qmldom::loadComposite() void tst_qmldom::testValueSource() { QByteArray qml = "import Qt 4.6\n" - "Rectangle { height: Follow { spring: 1.4; damping: .15; source: Math.min(Math.max(-130, value*2.2 - 130), 133); }}"; + "Rectangle { height: SpringFollow { spring: 1.4; damping: .15; source: Math.min(Math.max(-130, value*2.2 - 130), 133); }}"; QmlEngine freshEngine; QmlDomDocument document; @@ -135,7 +135,7 @@ void tst_qmldom::testValueSource() QmlDomObject valueSourceObject = valueSource.object(); QVERIFY(valueSourceObject.isValid()); - QVERIFY(valueSourceObject.objectType() == "Qt/Follow"); + QVERIFY(valueSourceObject.objectType() == "Qt/SpringFollow"); const QmlDomValue springValue = valueSourceObject.property("spring").value(); QVERIFY(!springValue.isInvalid()); -- cgit v0.12 From 32e81daf19c5b4524302359a97dd3dc743edc912 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:32:18 +1000 Subject: Update Repeater is now *after* items. --- tests/auto/declarative/repeater/tst_repeater.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/auto/declarative/repeater/tst_repeater.cpp b/tests/auto/declarative/repeater/tst_repeater.cpp index 1bb746b..68007a6 100644 --- a/tests/auto/declarative/repeater/tst_repeater.cpp +++ b/tests/auto/declarative/repeater/tst_repeater.cpp @@ -53,14 +53,18 @@ void tst_QFxRepeater::stringList() QCOMPARE(container->childItems().count(), data.count() + 3); + bool saw_repeater = false; for (int i = 0; i < container->childItems().count(); ++i) { if (i == 0) { QFxText *name = qobject_cast(container->childItems().at(i)); QVERIFY(name != 0); QCOMPARE(name->text(), QLatin1String("Zero")); - } else if (i == 1) { + } else if (i == container->childItems().count() - 2) { // The repeater itself + QFxRepeater *rep = qobject_cast(container->childItems().at(i)); + QCOMPARE(rep, repeater); + saw_repeater = true; continue; } else if (i == container->childItems().count() - 1) { QFxText *name = qobject_cast(container->childItems().at(i)); @@ -69,10 +73,10 @@ void tst_QFxRepeater::stringList() } else { QFxText *name = qobject_cast(container->childItems().at(i)); QVERIFY(name != 0); - QCOMPARE(name->text(), data.at(i-2)); + QCOMPARE(name->text(), data.at(i-1)); } - } + QVERIFY(saw_repeater); delete canvas; } -- cgit v0.12 From 896a5335efb375f67fef7cdff10c842046e61d3f Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:34:22 +1000 Subject: Fix --- tests/auto/declarative/pathview/tst_pathview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/declarative/pathview/tst_pathview.cpp b/tests/auto/declarative/pathview/tst_pathview.cpp index e2da191..6e670bf 100644 --- a/tests/auto/declarative/pathview/tst_pathview.cpp +++ b/tests/auto/declarative/pathview/tst_pathview.cpp @@ -21,7 +21,7 @@ private slots: private: QmlView *createView(const QString &filename); template - T *findItem(QFxItem *parent, const QString &id, int index=0); + T *findItem(QFxItem *parent, const QString &id, int index=-1); }; class TestModel : public QListModelInterface -- cgit v0.12 From b416be48930ed52bad15fa220142f9228e82bcf8 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Thu, 8 Oct 2009 17:34:34 +1000 Subject: Update list of tests --- tests/auto/declarative/declarative.pro | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index f2ddbb7..eef9da7 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -1,24 +1,32 @@ TEMPLATE = subdirs -SUBDIRS += datetimeformatter \ - numberformatter \ - qbindablemap \ +SUBDIRS += anchors \ + animations \ + datetimeformatter \ layouts \ listview \ + numberformatter \ pathview \ + qbindablemap \ + qfxloader \ + qfxpixmapcache \ qfxtext \ qfxtextedit \ - repeater \ - qmllanguage \ + qfxtextinput \ + qfxwebview \ + qmldom \ qmlecmascript \ - qmlmetaproperty \ + qmllanguage \ qmllist \ qmllistaccessor \ + qmlmetaproperty \ qmltimer \ - qfxloader \ - qfxwebview \ + repeater \ + sql \ states \ visual +SUBDIRS -= examples # Human-interactive + # Tests which should run in Pulse PULSE_TESTS = $$SUBDIRS PULSE_TESTS -= visual # All except 'visual' tests, allegedly too flaky -- cgit v0.12 From e08c4d393cbef8aa526328678ef4d71642b32f84 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 18:01:00 +1000 Subject: Rename label to labeltext Resolves scope collision between label property and label id --- demos/declarative/flickr/common/MediaLineEdit.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/demos/declarative/flickr/common/MediaLineEdit.qml b/demos/declarative/flickr/common/MediaLineEdit.qml index 4b21f66..f959bc5 100644 --- a/demos/declarative/flickr/common/MediaLineEdit.qml +++ b/demos/declarative/flickr/common/MediaLineEdit.qml @@ -6,18 +6,18 @@ Item { property string label property string text - width: Math.max(94,label.width + editor.width + 20) + width: Math.max(94,labeltext.width + editor.width + 20) height: buttonImage.height states: [ State { name: "Edit" PropertyChanges { - target: label + target: labeltext text: container.label + ": " } PropertyChanges { - target: label + target: labeltext x: 10 } PropertyChanges { @@ -78,7 +78,7 @@ Item { } Text { - id: label + id: labeltext font.bold: true color: "white" anchors.verticalCenter: container.verticalCenter @@ -93,7 +93,7 @@ Item { selectionColor: "green" width: 0 clip: true - anchors.left: label.right + anchors.left: labeltext.right anchors.verticalCenter: container.verticalCenter } Keys.forwardTo: [(returnKey), (editor)] -- cgit v0.12 From 6f5c3d1c6f9d3a826821d12139070e9772eae749 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 8 Oct 2009 18:30:19 +1000 Subject: Remove a bunch of unneeded semicolons. --- doc/src/declarative/qmlviewer.qdoc | 3 +++ src/declarative/debugger/qmldebug.h | 2 +- src/declarative/extra/qmlfontloader.cpp | 2 +- src/declarative/fx/qfxgridview.cpp | 2 +- src/declarative/fx/qfxitem.cpp | 10 ++++---- src/declarative/fx/qfxitem.h | 2 +- src/declarative/fx/qfxtextinput.h | 2 +- src/declarative/qml/qmlcomponentjs_p.h | 8 +++--- src/declarative/qml/qmlcontext.cpp | 2 +- src/declarative/qml/qmlvaluetype_p.h | 38 ++++++++++++++--------------- src/declarative/util/qmlpackage.cpp | 2 +- src/declarative/util/qmlpropertychanges.h | 2 +- src/declarative/util/qmlstateoperations.cpp | 2 +- 13 files changed, 40 insertions(+), 37 deletions(-) diff --git a/doc/src/declarative/qmlviewer.qdoc b/doc/src/declarative/qmlviewer.qdoc index 8228737..f153df2 100644 --- a/doc/src/declarative/qmlviewer.qdoc +++ b/doc/src/declarative/qmlviewer.qdoc @@ -49,6 +49,9 @@ toolkit. The \c qmlviewer reads a declarative user interface definition (\c .qml) file and displays the user interface it describes. + qmlviewer is a development tool. It is not intended to be + installed in a production environment. + \section1 Options When run with the \c -help option, qmlviewer shows available options. diff --git a/src/declarative/debugger/qmldebug.h b/src/declarative/debugger/qmldebug.h index 9fd5fae..681ee08 100644 --- a/src/declarative/debugger/qmldebug.h +++ b/src/declarative/debugger/qmldebug.h @@ -46,7 +46,7 @@ public: QObject *parent = 0); private: - Q_DECLARE_PRIVATE(QmlEngineDebug); + Q_DECLARE_PRIVATE(QmlEngineDebug) }; class Q_DECLARATIVE_EXPORT QmlDebugWatch : public QObject diff --git a/src/declarative/extra/qmlfontloader.cpp b/src/declarative/extra/qmlfontloader.cpp index 4497384..66c8567 100644 --- a/src/declarative/extra/qmlfontloader.cpp +++ b/src/declarative/extra/qmlfontloader.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QmlFontLoaderPrivate : public QObjectPrivate { - Q_DECLARE_PUBLIC(QmlFontLoader); + Q_DECLARE_PUBLIC(QmlFontLoader) public: QmlFontLoaderPrivate() : reply(0), status(QmlFontLoader::Null) {} diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index 9aa1198..a8b27f4 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -145,7 +145,7 @@ public: class QFxGridViewPrivate : public QFxFlickablePrivate { - Q_DECLARE_PUBLIC(QFxGridView); + Q_DECLARE_PUBLIC(QFxGridView) public: QFxGridViewPrivate() diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 4d31aaa..d6534a1 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -408,12 +408,12 @@ public: class QFxKeyNavigationAttached : public QObject, public QFxItemKeyFilter { Q_OBJECT - Q_DECLARE_PRIVATE(QFxKeyNavigationAttached); + Q_DECLARE_PRIVATE(QFxKeyNavigationAttached) - Q_PROPERTY(QFxItem *left READ left WRITE setLeft NOTIFY changed); - Q_PROPERTY(QFxItem *right READ right WRITE setRight NOTIFY changed); - Q_PROPERTY(QFxItem *up READ up WRITE setUp NOTIFY changed); - Q_PROPERTY(QFxItem *down READ down WRITE setDown NOTIFY changed); + Q_PROPERTY(QFxItem *left READ left WRITE setLeft NOTIFY changed) + Q_PROPERTY(QFxItem *right READ right WRITE setRight NOTIFY changed) + Q_PROPERTY(QFxItem *up READ up WRITE setUp NOTIFY changed) + Q_PROPERTY(QFxItem *down READ down WRITE setDown NOTIFY changed) public: QFxKeyNavigationAttached(QObject * = 0); diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 30c522f..bde0c9e 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -93,7 +93,7 @@ class Q_DECLARATIVE_EXPORT QFxItem : public QGraphicsObject, public QmlParserSta Q_PROPERTY(QmlList* transform READ transform DESIGNABLE false FINAL) Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin) Q_PROPERTY(bool smooth READ smoothTransform WRITE setSmoothTransform) - Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect); + Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect) Q_ENUMS(TransformOrigin) Q_CLASSINFO("DefaultProperty", "data") diff --git a/src/declarative/fx/qfxtextinput.h b/src/declarative/fx/qfxtextinput.h index b1e8b14..d5d0450 100644 --- a/src/declarative/fx/qfxtextinput.h +++ b/src/declarative/fx/qfxtextinput.h @@ -193,7 +193,7 @@ private Q_SLOTS: void updateRect(const QRect &r = QRect()); private: - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxTextInput); + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxTextInput) }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcomponentjs_p.h b/src/declarative/qml/qmlcomponentjs_p.h index cee3035..0f56766 100644 --- a/src/declarative/qml/qmlcomponentjs_p.h +++ b/src/declarative/qml/qmlcomponentjs_p.h @@ -73,10 +73,10 @@ class Q_DECLARATIVE_EXPORT QmlComponentJS : public QmlComponent public: QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0); QmlComponentJS(QmlEngine *, QObject *parent=0); - Q_PROPERTY(bool isNull READ isNull NOTIFY isNullChanged); - Q_PROPERTY(bool isReady READ isReady NOTIFY isReadyChanged); - Q_PROPERTY(bool isError READ isError NOTIFY isErrorChanged); - Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged); + Q_PROPERTY(bool isNull READ isNull NOTIFY isNullChanged) + Q_PROPERTY(bool isReady READ isReady NOTIFY isReadyChanged) + Q_PROPERTY(bool isError READ isError NOTIFY isErrorChanged) + Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged) Q_INVOKABLE QScriptValue createObject(); Q_INVOKABLE QString errorsString() const; diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 97ab375..0632ef7 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -168,7 +168,7 @@ void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) \code class MyDataSet : ... { ... - Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged); + Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged) ... }; diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h index a56feec..da5e972 100644 --- a/src/declarative/qml/qmlvaluetype_p.h +++ b/src/declarative/qml/qmlvaluetype_p.h @@ -85,8 +85,8 @@ public: class QmlPointFValueType : public QmlValueType { - Q_PROPERTY(qreal x READ x WRITE setX); - Q_PROPERTY(qreal y READ y WRITE setY); + Q_PROPERTY(qreal x READ x WRITE setX) + Q_PROPERTY(qreal y READ y WRITE setY) Q_OBJECT public: QmlPointFValueType(QObject *parent = 0); @@ -107,8 +107,8 @@ private: class QmlPointValueType : public QmlValueType { - Q_PROPERTY(int x READ x WRITE setX); - Q_PROPERTY(int y READ y WRITE setY); + Q_PROPERTY(int x READ x WRITE setX) + Q_PROPERTY(int y READ y WRITE setY) Q_OBJECT public: QmlPointValueType(QObject *parent = 0); @@ -129,8 +129,8 @@ private: class QmlSizeFValueType : public QmlValueType { - Q_PROPERTY(qreal width READ width WRITE setWidth); - Q_PROPERTY(qreal height READ height WRITE setHeight); + Q_PROPERTY(qreal width READ width WRITE setWidth) + Q_PROPERTY(qreal height READ height WRITE setHeight) Q_OBJECT public: QmlSizeFValueType(QObject *parent = 0); @@ -151,8 +151,8 @@ private: class QmlSizeValueType : public QmlValueType { - Q_PROPERTY(int width READ width WRITE setWidth); - Q_PROPERTY(int height READ height WRITE setHeight); + Q_PROPERTY(int width READ width WRITE setWidth) + Q_PROPERTY(int height READ height WRITE setHeight) Q_OBJECT public: QmlSizeValueType(QObject *parent = 0); @@ -173,10 +173,10 @@ private: class QmlRectFValueType : public QmlValueType { - Q_PROPERTY(qreal x READ x WRITE setX); - Q_PROPERTY(qreal y READ y WRITE setY); - Q_PROPERTY(qreal width READ width WRITE setWidth); - Q_PROPERTY(qreal height READ height WRITE setHeight); + Q_PROPERTY(qreal x READ x WRITE setX) + Q_PROPERTY(qreal y READ y WRITE setY) + Q_PROPERTY(qreal width READ width WRITE setWidth) + Q_PROPERTY(qreal height READ height WRITE setHeight) Q_OBJECT public: QmlRectFValueType(QObject *parent = 0); @@ -202,10 +202,10 @@ private: class QmlRectValueType : public QmlValueType { - Q_PROPERTY(int x READ x WRITE setX); - Q_PROPERTY(int y READ y WRITE setY); - Q_PROPERTY(int width READ width WRITE setWidth); - Q_PROPERTY(int height READ height WRITE setHeight); + Q_PROPERTY(int x READ x WRITE setX) + Q_PROPERTY(int y READ y WRITE setY) + Q_PROPERTY(int width READ width WRITE setWidth) + Q_PROPERTY(int height READ height WRITE setHeight) Q_OBJECT public: QmlRectValueType(QObject *parent = 0); @@ -231,9 +231,9 @@ private: class QmlVector3DValueType : public QmlValueType { - Q_PROPERTY(qreal x READ x WRITE setX); - Q_PROPERTY(qreal y READ y WRITE setY); - Q_PROPERTY(qreal z READ z WRITE setZ); + Q_PROPERTY(qreal x READ x WRITE setX) + Q_PROPERTY(qreal y READ y WRITE setY) + Q_PROPERTY(qreal z READ z WRITE setZ) Q_OBJECT public: QmlVector3DValueType(QObject *parent = 0); diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp index 8483080..912bb6b 100644 --- a/src/declarative/util/qmlpackage.cpp +++ b/src/declarative/util/qmlpackage.cpp @@ -59,7 +59,7 @@ public: QmlPackageAttached(QObject *parent); virtual ~QmlPackageAttached(); - Q_PROPERTY(QString name READ name WRITE setName); + Q_PROPERTY(QString name READ name WRITE setName) QString name() const; void setName(const QString &n); diff --git a/src/declarative/util/qmlpropertychanges.h b/src/declarative/util/qmlpropertychanges.h index 8d338f1..2931cdb 100644 --- a/src/declarative/util/qmlpropertychanges.h +++ b/src/declarative/util/qmlpropertychanges.h @@ -58,7 +58,7 @@ class Q_DECLARATIVE_EXPORT QmlPropertyChanges : public QmlStateOperation Q_PROPERTY(QObject *target READ object WRITE setObject) Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues) - Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit); + Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit) public: QmlPropertyChanges(); ~QmlPropertyChanges(); diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index 921aa6c..716cec4 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -189,7 +189,7 @@ QmlStateOperation::ActionList QmlParentChange::actions() class AccessibleFxItem : public QFxItem { Q_OBJECT - Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxItem); + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxItem) public: int siblingIndex() { Q_D(QFxItem); -- cgit v0.12 From 5537833ea06a60a5ed6027c9d3d707291b2673ee Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 19:45:44 +1000 Subject: Fix messed up merge --- src/corelib/animation/qabstractanimation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index a45f60b..a8c3504 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -246,13 +246,13 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) // this is needed if we unregister an animation while its running if (idx <= currentAnimationIdx) --currentAnimationIdx; - if (animations.isEmpty()) + if (animations.isEmpty() && !startStopAnimationTimer.isActive()) startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); } else { animationsToStart.removeOne(animation); } - if (!startStopAnimationTimer.isActive()) - startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this); + + QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false; } void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) -- cgit v0.12 From f41e84f6ce70e8b05f6cfcadc6780dc5ecc2f8b0 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 19:51:51 +1000 Subject: Zero bindingBits correctly --- src/declarative/qml/qmlengine.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 9ee0d1b..ccdf6cf 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -534,9 +534,10 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit) bindingBits = (quint32 *)realloc(bindingBits, arraySize * sizeof(quint32)); + memset(bindingBits + oldArraySize, - sizeof(quint32) * (arraySize - oldArraySize), - 0x00); + 0x00, + sizeof(quint32) * (arraySize - oldArraySize)); bindingBitsSize = arraySize * 32; } -- cgit v0.12 From d9f715adfbd0483f113f3108d5285c31833763c1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 19:52:18 +1000 Subject: Small optimization --- src/declarative/qml/qmlobjectscriptclass.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index d3a2a22..41573a2 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -214,12 +214,13 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); } - QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); - if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { - QObject *rv = *(QObject **)var.constData(); + QObject *rv = 0; + void *args[] = { &rv, 0 }; + QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); return newQObject(rv); } else { + QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); return enginePriv->scriptValueFromVariant(var); } -- cgit v0.12 From 0fcc46e34c7feedfa1758ead64b09be59813f7d1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 19:52:32 +1000 Subject: Fix visual model crash at shutdown due to dangling pointer --- src/declarative/fx/qfxvisualitemmodel.cpp | 76 +++++++++++++++++++------------ 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index b7248ea..943f909 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -239,6 +239,10 @@ class QFxVisualDataModelPrivate : public QObjectPrivate public: QFxVisualDataModelPrivate(QmlContext *); + static QFxVisualDataModelPrivate *get(QFxVisualDataModel *m) { + return static_cast(QObjectPrivate::get(m)); + } + QGuard m_listModelInterface; QGuard m_abstractItemModel; QGuard m_visualItemModel; @@ -363,7 +367,8 @@ class QFxVisualDataModelData : public QObject { Q_OBJECT public: - QFxVisualDataModelData(int index, QFxVisualDataModelPrivate *model); + QFxVisualDataModelData(int index, QFxVisualDataModel *model); + ~QFxVisualDataModelData(); Q_PROPERTY(int index READ index NOTIFY indexChanged) int index() const; @@ -379,7 +384,7 @@ Q_SIGNALS: private: friend class QFxVisualDataModelDataMetaObject; int m_index; - QFxVisualDataModelPrivate *m_model; + QGuard m_model; QFxVisualDataModelDataMetaObject *m_meta; }; @@ -404,15 +409,19 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha QFxVisualDataModelData *data = static_cast(object()); - if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel) - && data->m_model->m_listAccessor) { - data->m_model->ensureRoles(); - if (data->m_model->m_roleNames.contains(QLatin1String(name))) + if (!data->m_model) + return -1; + + QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model); + + if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { + model->ensureRoles(); + if (model->m_roleNames.contains(QLatin1String(name))) return QmlOpenMetaObject::createProperty(name, type); } else { - data->m_model->ensureRoles(); + model->ensureRoles(); const QLatin1String sname(name); - if (data->m_model->m_roleNames.contains(sname)) + if (model->m_roleNames.contains(sname)) return QmlOpenMetaObject::createProperty(name, type); } return -1; @@ -425,45 +434,48 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro QFxVisualDataModelData *data = static_cast(object()); + + Q_ASSERT(data->m_model); + QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model); + QString name = QLatin1String(prop.name()); - if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel) - && data->m_model->m_listAccessor) { + if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { if (name == QLatin1String("modelData")) { - if (data->m_model->m_listAccessor->type() == QmlListAccessor::Instance) { - QObject *object = data->m_model->m_listAccessor->at(0).value(); + if (model->m_listAccessor->type() == QmlListAccessor::Instance) { + QObject *object = model->m_listAccessor->at(0).value(); return object->metaObject()->property(1).read(object); // the first property after objectName } - return data->m_model->m_listAccessor->at(data->m_index); + return model->m_listAccessor->at(data->m_index); } else { // return any property of a single object instance. - QObject *object = data->m_model->m_listAccessor->at(0).value(); + QObject *object = model->m_listAccessor->at(0).value(); return object->property(prop.name()); } - } else if (data->m_model->m_listModelInterface) { - data->m_model->ensureRoles(); - QHash::const_iterator it = data->m_model->m_roleNames.find(name); - if (it != data->m_model->m_roleNames.end()) { + } else if (model->m_listModelInterface) { + model->ensureRoles(); + QHash::const_iterator it = model->m_roleNames.find(name); + if (it != model->m_roleNames.end()) { roles.append(*it); - QHash values = data->m_model->m_listModelInterface->data(data->m_index, QList() << *it); + QHash values = model->m_listModelInterface->data(data->m_index, QList() << *it); if (values.isEmpty()) return QVariant(); else return values.value(*it); - } else if (data->m_model->m_roles.count() == 1 && name == QLatin1String("modelData")) { + } else if (model->m_roles.count() == 1 && name == QLatin1String("modelData")) { //for compatability with other lists, assign modelData if there is only a single role - QHash values = data->m_model->m_listModelInterface->data(data->m_index, QList() << data->m_model->m_roles.first()); + QHash values = model->m_listModelInterface->data(data->m_index, QList() << model->m_roles.first()); if (values.isEmpty()) return QVariant(); else return *values.begin(); } - } else if (data->m_model->m_abstractItemModel) { - data->m_model->ensureRoles(); - QHash::const_iterator it = data->m_model->m_roleNames.find(name); - if (it != data->m_model->m_roleNames.end()) { + } else if (model->m_abstractItemModel) { + model->ensureRoles(); + QHash::const_iterator it = model->m_roleNames.find(name); + if (it != model->m_roleNames.end()) { roles.append(*it); - QModelIndex index = data->m_model->m_abstractItemModel->index(data->m_index, 0); - return data->m_model->m_abstractItemModel->data(index, *it); + QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0); + return model->m_abstractItemModel->data(index, *it); } } Q_ASSERT(!"Can never be reached"); @@ -471,12 +483,16 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro } QFxVisualDataModelData::QFxVisualDataModelData(int index, - QFxVisualDataModelPrivate *model) + QFxVisualDataModel *model) : m_index(index), m_model(model), m_meta(new QFxVisualDataModelDataMetaObject(this)) { } +QFxVisualDataModelData::~QFxVisualDataModelData() +{ +} + int QFxVisualDataModelData::index() const { return m_index; @@ -752,7 +768,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp QmlContext *ccontext = d->m_context; if (!ccontext) ccontext = qmlContext(this); QmlContext *ctxt = new QmlContext(ccontext); - QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d); + QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this); ctxt->setContextProperty(QLatin1String("model"), data); ctxt->addDefaultObject(data); nobj = d->m_delegate->beginCreate(ctxt); @@ -821,7 +837,7 @@ QVariant QFxVisualDataModel::evaluate(int index, const QString &expression, QObj QmlContext *ccontext = d->m_context; if (!ccontext) ccontext = qmlContext(this); QmlContext *ctxt = new QmlContext(ccontext); - QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d); + QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this); ctxt->addDefaultObject(data); QmlExpression e(ctxt, expression, objectContext); e.setTrackChange(false); -- cgit v0.12 From 7a5659038c6b558f4edc49150126787a3930102b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 20:05:18 +1000 Subject: Incorrect use of Script {} --- demos/declarative/contacts/FieldText.qml | 40 +++++++++++----------- demos/declarative/contacts/RemoveButton.qml | 23 ++++++------- .../declarative/webbrowser/fieldtext/FieldText.qml | 2 -- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/demos/declarative/contacts/FieldText.qml b/demos/declarative/contacts/FieldText.qml index d30d4d8..2e8b60d 100644 --- a/demos/declarative/contacts/FieldText.qml +++ b/demos/declarative/contacts/FieldText.qml @@ -9,29 +9,29 @@ Rectangle { property var label: "" onTextChanged: { reset() } signal confirmed - resources: [ - Script { - function edit() { - if (!contacts.mouseGrabbed) { - fieldText.state='editing'; - contacts.mouseGrabbed=true; - } - } - function confirm() { - fieldText.text = textEdit.text; - fieldText.state=''; - contacts.mouseGrabbed=false; - fieldText.confirmed(); - } - function reset() { - textEdit.text = fieldText.text; - fieldText.state=''; - contacts.mouseGrabbed=false; + Script { + + function edit() { + if (!contacts.mouseGrabbed) { + fieldText.state='editing'; + contacts.mouseGrabbed=true; } - } - ] + function confirm() { + fieldText.text = textEdit.text; + fieldText.state=''; + contacts.mouseGrabbed=false; + fieldText.confirmed(); + } + function reset() { + textEdit.text = fieldText.text; + fieldText.state=''; + contacts.mouseGrabbed=false; + } + + } + Image { id: cancelIcon width: 22 diff --git a/demos/declarative/contacts/RemoveButton.qml b/demos/declarative/contacts/RemoveButton.qml index cc858c3..2c3cc9e 100644 --- a/demos/declarative/contacts/RemoveButton.qml +++ b/demos/declarative/contacts/RemoveButton.qml @@ -8,21 +8,20 @@ Rectangle { radius: 5 property var expandedWidth: 230 signal confirmed - resources: [ - Script { - function toggle() { - if (removeButton.state == 'opened') { - removeButton.state = ''; - contacts.mouseGrabbed=false; - } else { - if (!contacts.mouseGrabbed) { - removeButton.state = 'opened'; - contacts.mouseGrabbed=true; - } + Script { + function toggle() { + if (removeButton.state == 'opened') { + removeButton.state = ''; + contacts.mouseGrabbed=false; + } else { + if (!contacts.mouseGrabbed) { + removeButton.state = 'opened'; + contacts.mouseGrabbed=true; } } } - ] + } + Image { id: trashIcon width: 22 diff --git a/demos/declarative/webbrowser/fieldtext/FieldText.qml b/demos/declarative/webbrowser/fieldtext/FieldText.qml index fe55185..2adfbbf 100644 --- a/demos/declarative/webbrowser/fieldtext/FieldText.qml +++ b/demos/declarative/webbrowser/fieldtext/FieldText.qml @@ -10,7 +10,6 @@ Item { signal cancelled signal startEdit - resources: [ Script { function edit() { @@ -36,7 +35,6 @@ Item { } } - ] Image { id: cancelIcon -- cgit v0.12 From 931350a9cb24f30e6fd6c227dbdc40937d59a705 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Oct 2009 22:46:57 +1000 Subject: Move Q_PROPERTY()'s to top of object Q_PROPERTY() macros without a semicolon inside a class access block (public:) confuses moc into ignoring Q_INVOKABLES --- src/declarative/qml/qmlcomponentjs_p.h | 8 ++++---- src/declarative/util/qmlpackage.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/declarative/qml/qmlcomponentjs_p.h b/src/declarative/qml/qmlcomponentjs_p.h index 0f56766..3213929 100644 --- a/src/declarative/qml/qmlcomponentjs_p.h +++ b/src/declarative/qml/qmlcomponentjs_p.h @@ -69,14 +69,14 @@ class Q_DECLARATIVE_EXPORT QmlComponentJS : public QmlComponent { Q_OBJECT Q_DECLARE_PRIVATE(QmlComponentJS) - friend class QmlEngine; -public: - QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0); - QmlComponentJS(QmlEngine *, QObject *parent=0); Q_PROPERTY(bool isNull READ isNull NOTIFY isNullChanged) Q_PROPERTY(bool isReady READ isReady NOTIFY isReadyChanged) Q_PROPERTY(bool isError READ isError NOTIFY isErrorChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged) + friend class QmlEngine; +public: + QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0); + QmlComponentJS(QmlEngine *, QObject *parent=0); Q_INVOKABLE QScriptValue createObject(); Q_INVOKABLE QString errorsString() const; diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp index 912bb6b..7df8453 100644 --- a/src/declarative/util/qmlpackage.cpp +++ b/src/declarative/util/qmlpackage.cpp @@ -55,11 +55,11 @@ public: class QmlPackageAttached : public QObject { Q_OBJECT +Q_PROPERTY(QString name READ name WRITE setName) public: QmlPackageAttached(QObject *parent); virtual ~QmlPackageAttached(); - Q_PROPERTY(QString name READ name WRITE setName) QString name() const; void setName(const QString &n); -- cgit v0.12 From f21c1f444de012c38207ed93db8c3470cf197631 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 9 Oct 2009 10:34:17 +1000 Subject: GraphicsObjectContainer cleanup. Also fixes initial size of widget if the container has an explicit size set. --- src/declarative/fx/qfxgraphicsobjectcontainer.cpp | 119 ++++++++++++++-------- src/declarative/fx/qfxgraphicsobjectcontainer.h | 8 +- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/declarative/fx/qfxgraphicsobjectcontainer.cpp b/src/declarative/fx/qfxgraphicsobjectcontainer.cpp index c0cac6c..5a61d12 100644 --- a/src/declarative/fx/qfxgraphicsobjectcontainer.cpp +++ b/src/declarative/fx/qfxgraphicsobjectcontainer.cpp @@ -43,9 +43,42 @@ #include #include #include +#include QT_BEGIN_NAMESPACE +class QFxGraphicsObjectContainerPrivate : public QFxItemPrivate +{ + Q_DECLARE_PUBLIC(QFxGraphicsObjectContainer) + +public: + QFxGraphicsObjectContainerPrivate() : QFxItemPrivate(), graphicsObject(0), syncedResize(false) + { } + + void _q_updateSize(); + + void setFiltering(bool on) + { + Q_Q(QFxGraphicsObjectContainer); + if (graphicsObject && graphicsObject->isWidget()) { + if (!on) { + graphicsObject->removeEventFilter(q); + QObject::disconnect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize())); + QObject::disconnect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize())); + } else { + graphicsObject->installEventFilter(q); + QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize())); + QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize())); + } + } + } + + + QGraphicsObject *graphicsObject; + bool syncedResize; +}; + + /*! \qmlclass GraphicsObjectContainer QFxGraphicsObjectContainer \brief The GraphicsObjectContainer element allows you to add QGraphicsObjects into Fluid UI elements. @@ -61,7 +94,7 @@ QML_DEFINE_NOCREATE_TYPE(QGraphicsObject) QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,GraphicsObjectContainer,QFxGraphicsObjectContainer) QFxGraphicsObjectContainer::QFxGraphicsObjectContainer(QFxItem *parent) -: QFxItem(parent), _graphicsObject(0), _syncedResize(false) +: QFxItem(*new QFxGraphicsObjectContainerPrivate, parent) { } @@ -71,7 +104,8 @@ QFxGraphicsObjectContainer::~QFxGraphicsObjectContainer() QGraphicsObject *QFxGraphicsObjectContainer::graphicsObject() const { - return _graphicsObject; + Q_D(const QFxGraphicsObjectContainer); + return d->graphicsObject; } /*! @@ -80,30 +114,45 @@ QGraphicsObject *QFxGraphicsObjectContainer::graphicsObject() const */ void QFxGraphicsObjectContainer::setGraphicsObject(QGraphicsObject *object) { - if (object == _graphicsObject) + Q_D(QFxGraphicsObjectContainer); + if (object == d->graphicsObject) return; - //### what should we do with previously set object? + //### remove previously set item? + + d->setFiltering(false); + + d->graphicsObject = object; - _graphicsObject = object; + if (d->graphicsObject) { + d->graphicsObject->setParentItem(this); - if (_graphicsObject) { - _graphicsObject->setParentItem(this); + if (d->syncedResize && d->graphicsObject->isWidget()) { + QGraphicsWidget *gw = static_cast(d->graphicsObject); + QSizeF gwSize = gw->size(); //### should we use sizeHint? + QSizeF newSize = gwSize; + if (heightValid()) + newSize.setHeight(height()); + if (widthValid()) + newSize.setWidth(width()); + if (gwSize != newSize) + gw->resize(newSize); - if (_syncedResize && _graphicsObject->isWidget()) { - _graphicsObject->installEventFilter(this); - QSizeF newSize = static_cast(_graphicsObject)->size(); //### use sizeHint? - setImplicitWidth(newSize.width()); - setImplicitHeight(newSize.height()); + gwSize = gw->size(); + setImplicitWidth(gwSize.width()); + setImplicitHeight(gwSize.height()); + + d->setFiltering(true); } } } QVariant QFxGraphicsObjectContainer::itemChange(GraphicsItemChange change, const QVariant &value) { + Q_D(QFxGraphicsObjectContainer); if (change == ItemSceneHasChanged) { - QGraphicsObject *o = _graphicsObject; - _graphicsObject = 0; + QGraphicsObject *o = d->graphicsObject; + d->graphicsObject = 0; setGraphicsObject(o); } return QFxItem::itemChange(change, value); @@ -111,9 +160,10 @@ QVariant QFxGraphicsObjectContainer::itemChange(GraphicsItemChange change, const bool QFxGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e) { - if (watched == _graphicsObject && e->type() == QEvent::GraphicsSceneResize) { - if (_graphicsObject && _graphicsObject->isWidget() && _syncedResize) { - QSizeF newSize = static_cast(_graphicsObject)->size(); + Q_D(QFxGraphicsObjectContainer); + if (watched == d->graphicsObject && e->type() == QEvent::GraphicsSceneResize) { + if (d->graphicsObject && d->graphicsObject->isWidget() && d->syncedResize) { + QSizeF newSize = static_cast(d->graphicsObject)->size(); setImplicitWidth(newSize.width()); setImplicitHeight(newSize.height()); } @@ -142,40 +192,27 @@ bool QFxGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e) */ bool QFxGraphicsObjectContainer::synchronizedResizing() const { - return _syncedResize; + Q_D(const QFxGraphicsObjectContainer); + return d->syncedResize; } void QFxGraphicsObjectContainer::setSynchronizedResizing(bool on) { - if (on == _syncedResize) + Q_D(QFxGraphicsObjectContainer); + if (on == d->syncedResize) return; - if (_graphicsObject && _graphicsObject->isWidget()) { - if (!on) { - _graphicsObject->removeEventFilter(this); - disconnect(this, SIGNAL(widthChanged()), this, SLOT(_q_updateSize())); - disconnect(this, SIGNAL(heightChanged()), this, SLOT(_q_updateSize())); - } - } - - _syncedResize = on; - - if (_graphicsObject && _graphicsObject->isWidget()) { - if (on) { - _graphicsObject->installEventFilter(this); - connect(this, SIGNAL(widthChanged()), this, SLOT(_q_updateSize())); - connect(this, SIGNAL(heightChanged()), this, SLOT(_q_updateSize())); - } - } + d->syncedResize = on; + d->setFiltering(on); } -void QFxGraphicsObjectContainer::_q_updateSize() +void QFxGraphicsObjectContainerPrivate::_q_updateSize() { - if (!_graphicsObject || !_graphicsObject->isWidget() || !_syncedResize) + if (!graphicsObject || !graphicsObject->isWidget() || !syncedResize) return; - QGraphicsWidget *gw = static_cast(_graphicsObject); - const QSizeF newSize(width(), height()); + QGraphicsWidget *gw = static_cast(graphicsObject); + const QSizeF newSize(width, height); gw->resize(newSize); //### will respecting the widgets min/max ever get us in trouble? (all other items always @@ -189,3 +226,5 @@ void QFxGraphicsObjectContainer::_q_updateSize() } QT_END_NAMESPACE + +#include "moc_qfxgraphicsobjectcontainer.cpp" diff --git a/src/declarative/fx/qfxgraphicsobjectcontainer.h b/src/declarative/fx/qfxgraphicsobjectcontainer.h index a8b7c8c..656a7f8 100644 --- a/src/declarative/fx/qfxgraphicsobjectcontainer.h +++ b/src/declarative/fx/qfxgraphicsobjectcontainer.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QGraphicsObject; +class QFxGraphicsObjectContainerPrivate; class Q_DECLARATIVE_EXPORT QFxGraphicsObjectContainer : public QFxItem { @@ -74,12 +75,9 @@ protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); bool eventFilter(QObject *watched, QEvent *e); -private Q_SLOTS: - void _q_updateSize(); - private: - QGraphicsObject *_graphicsObject; - bool _syncedResize; + Q_PRIVATE_SLOT(d_func(), void _q_updateSize()) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxGraphicsObjectContainer) }; QT_END_NAMESPACE -- cgit v0.12 From 3d6132ae9224b9374285d9eda062a815c4582f7c Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 9 Oct 2009 10:45:00 +1000 Subject: No need for temporary currentItem --- src/declarative/fx/qfxgridview.cpp | 15 +++------------ src/declarative/fx/qfxlistview.cpp | 19 ++++--------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index a8b27f4..2d25d56 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -149,7 +149,7 @@ class QFxGridViewPrivate : public QFxFlickablePrivate public: QFxGridViewPrivate() - : model(0), currentItem(0), tmpCurrent(0), flow(QFxGridView::LeftToRight) + : model(0), currentItem(0), flow(QFxGridView::LeftToRight) , visiblePos(0), visibleIndex(0) , currentIndex(-1) , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1) , highlightComponent(0), highlight(0), trackedItem(0) @@ -298,7 +298,6 @@ public: QList visibleItems; QHash unrequestedItems; FxGridItem *currentItem; - QFxItem *tmpCurrent; QFxGridView::Flow flow; int visiblePos; int visibleIndex; @@ -640,10 +639,6 @@ void QFxGridViewPrivate::updateCurrent(int modelIndex) return; } - if (tmpCurrent) { - delete tmpCurrent; - tmpCurrent = 0; - } FxGridItem *oldCurrentItem = currentItem; currentIndex = modelIndex; currentItem = createItem(modelIndex); @@ -821,12 +816,8 @@ void QFxGridView::setCurrentIndex(int index) QFxItem *QFxGridView::currentItem() { Q_D(QFxGridView); - if (!d->currentItem) { - // Always return something valid - if (!d->tmpCurrent) - d->tmpCurrent = new QFxItem(viewport()); - return d->tmpCurrent; - } + if (!d->currentItem) + return 0; return d->currentItem->item; } diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 1247021..5afd881 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -170,15 +170,15 @@ class QFxListViewPrivate : public QFxFlickablePrivate public: QFxListViewPrivate() - : model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical) + : model(0), currentItem(0), orient(Qt::Vertical) , visiblePos(0), visibleIndex(0) , averageSize(100.0), currentIndex(-1), requestedIndex(-1) , highlightRangeStart(0), highlightRangeEnd(0) , highlightComponent(0), highlight(0), trackedItem(0) , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0.0) + , highlightMoveSpeed(400), highlightResizeSpeed(400) , ownModel(false), wrap(false), autoHighlight(true) , haveHighlightRange(false), strictHighlightRange(false) - , highlightMoveSpeed(400), highlightResizeSpeed(400) {} void init(); @@ -371,7 +371,6 @@ public: QList visibleItems; QHash unrequestedItems; FxListItem *currentItem; - QFxItem *tmpCurrent; Qt::Orientation orient; int visiblePos; int visibleIndex; @@ -752,10 +751,6 @@ void QFxListViewPrivate::updateCurrent(int modelIndex) return; } - if (tmpCurrent) { - delete tmpCurrent; - tmpCurrent = 0; - } FxListItem *oldCurrentItem = currentItem; currentIndex = modelIndex; currentItem = createItem(modelIndex); @@ -991,14 +986,8 @@ void QFxListView::setCurrentIndex(int index) QFxItem *QFxListView::currentItem() { Q_D(QFxListView); - if (!d->currentItem) { - // Always return something valid - if (!d->tmpCurrent) { - d->tmpCurrent = new QFxItem; - d->tmpCurrent->setParent(viewport()); - } - return d->tmpCurrent; - } + if (!d->currentItem) + return 0; return d->currentItem->item; } -- cgit v0.12 From b957118a2d2f44cec5f1a0709da26a5c685cc344 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 11:10:43 +1000 Subject: Fix example errors --- examples/declarative/layouts/Button.qml | 8 ++++---- examples/declarative/webview/content/FieldText.qml | 2 -- examples/declarative/xmldata/yahoonews.qml | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/declarative/layouts/Button.qml b/examples/declarative/layouts/Button.qml index 6c2fd8d..1fa0dee 100644 --- a/examples/declarative/layouts/Button.qml +++ b/examples/declarative/layouts/Button.qml @@ -1,16 +1,16 @@ import Qt 4.6 -Rectangle { border.color: "black"; color: "steelblue"; radius: 5; width: pix.width + text.width + 13; height: pix.height + 10; id: page +Rectangle { border.color: "black"; color: "steelblue"; radius: 5; width: pix.width + textelement.width + 13; height: pix.height + 10; id: page property string text property string icon signal clicked Image { id: pix; x: 5; y:5; source: parent.icon} - Text { id: text; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;} + Text { id: textelement; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;} MouseRegion{ id:mr; anchors.fill: parent; onClicked: {parent.focus = true; page.clicked()}} states: State{ name:"pressed"; when:mr.pressed - PropertyChanges {target:text; x: 5} - PropertyChanges {target:pix; x:text.x+text.width + 3} + PropertyChanges {target:textelement; x: 5} + PropertyChanges {target:pix; x:textelement.x+textelement.width + 3} } transitions: diff --git a/examples/declarative/webview/content/FieldText.qml b/examples/declarative/webview/content/FieldText.qml index fe55185..2adfbbf 100644 --- a/examples/declarative/webview/content/FieldText.qml +++ b/examples/declarative/webview/content/FieldText.qml @@ -10,7 +10,6 @@ Item { signal cancelled signal startEdit - resources: [ Script { function edit() { @@ -36,7 +35,6 @@ Item { } } - ] Image { id: cancelIcon diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml index bad1d88..6d43f46 100644 --- a/examples/declarative/xmldata/yahoonews.qml +++ b/examples/declarative/xmldata/yahoonews.qml @@ -32,7 +32,7 @@ Rectangle { height: wrapper.height + 10 MouseRegion { anchors.fill: wrapper - onPressed: { delegate.ListView.list.currentIndex = index; } + onPressed: { delegate.ListView.view.currentIndex = index; } onClicked: { if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';} } } Rectangle { -- cgit v0.12 From 8e56f62a7155ec8f8e8af07100675fd6185bf481 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 9 Oct 2009 11:25:28 +1000 Subject: Remove some warnings. --- src/declarative/qml/qmlxmlhttprequest.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index 65c5b16..0bc927c 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -1190,7 +1190,7 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object")); if (context->argumentCount() < 2 || context->argumentCount() > 5) - return context->throwError(QScriptContext::SyntaxError, "Incorrect argument count"); + return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count")); // Argument 0 - Method QString method = context->argument(0).toString().toUpper(); @@ -1198,7 +1198,7 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin method != QLatin1String("PUT") && method != QLatin1String("HEAD") && method != QLatin1String("POST")) - return context->throwError(QScriptContext::SyntaxError, "Unsupported method"); + return context->throwError(QScriptContext::SyntaxError, QLatin1String("Unsupported method")); // Argument 1 - URL @@ -1209,12 +1209,12 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin if (ctxt) url = ctxt->resolvedUrl(url); else - return context->throwError(QScriptContext::SyntaxError, "Relative URLs not supported"); + return context->throwError(QScriptContext::SyntaxError, QLatin1String("Relative URLs not supported")); } // Argument 2 - async (optional) if (context->argumentCount() > 2 && !context->argument(2).toBoolean()) - return context->throwError(QScriptContext::SyntaxError, "Synchronous call not supported"); + return context->throwError(QScriptContext::SyntaxError, QLatin1String("Synchronous call not supported")); // Argument 3/4 - user/pass (optional) @@ -1242,12 +1242,12 @@ static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object")); if (context->argumentCount() != 2) - return context->throwError(QScriptContext::SyntaxError, "Incorrect argument count"); + return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count")); if (request->readyState() != QmlXMLHttpRequest::Opened || request->sendFlag()) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); QString name = context->argument(0).toString(); @@ -1289,10 +1289,10 @@ static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngin if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object")); if (request->readyState() != QmlXMLHttpRequest::Opened) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); if (request->sendFlag()) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); QByteArray data; if (context->argumentCount() > 0) @@ -1324,7 +1324,7 @@ static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, if (request->readyState() != QmlXMLHttpRequest::Loading && request->readyState() != QmlXMLHttpRequest::Done && request->readyState() != QmlXMLHttpRequest::HeadersReceived) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); QString headerName = context->argument(0).toString(); @@ -1342,7 +1342,7 @@ static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *cont if (request->readyState() != QmlXMLHttpRequest::Loading && request->readyState() != QmlXMLHttpRequest::Done && request->readyState() != QmlXMLHttpRequest::HeadersReceived) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); return QScriptValue(request->headers()); } @@ -1363,7 +1363,7 @@ static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEng if (request->readyState() == QmlXMLHttpRequest::Unsent || request->readyState() == QmlXMLHttpRequest::Opened) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); if (request->errorFlag()) return QScriptValue(0); @@ -1378,7 +1378,7 @@ static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScrip if (request->readyState() == QmlXMLHttpRequest::Unsent || request->readyState() == QmlXMLHttpRequest::Opened) - return context->throwError(INVALID_STATE_ERR, "Invalid state"); + return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state")); if (request->errorFlag()) return QScriptValue(0); -- cgit v0.12 From 8cefc95e3d91cb16ef6a7b16c18ef1e23a3911a9 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 12:43:43 +1000 Subject: Add missing NOTIFY --- doc/src/declarative/qmlmodels.qdoc | 2 +- src/declarative/fx/qfxborderimage.cpp | 4 ++-- src/declarative/fx/qfxborderimage.h | 7 ++++--- src/declarative/fx/qfxgridview.cpp | 4 ++-- src/declarative/fx/qfxgridview.h | 7 ++++--- src/declarative/fx/qfxlistview.cpp | 1 + src/declarative/fx/qfxlistview.h | 5 +++-- src/declarative/fx/qfxpositioners.cpp | 1 + src/declarative/fx/qfxpositioners.h | 3 ++- 9 files changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc index eca81cd..d0a5464 100644 --- a/doc/src/declarative/qmlmodels.qdoc +++ b/doc/src/declarative/qmlmodels.qdoc @@ -63,7 +63,7 @@ There are a number of QML elements that operate using data models: \o ListView \o GridView \o PathView -\o \l {qml-repeater}{Repeater} +\o \l Repeater \endlist QML supports several types of data model, which may be provided by QML diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 6616912..8f98a11 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -273,7 +273,7 @@ void QFxBorderImage::setHorizontalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->horizontalTileMode) { d->horizontalTileMode = t; - emit tileModeChanged(); + emit horizontalTileModeChanged(); update(); } } @@ -289,7 +289,7 @@ void QFxBorderImage::setVerticalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->verticalTileMode) { d->verticalTileMode = t; - emit tileModeChanged(); + emit verticalTileModeChanged(); update(); } } diff --git a/src/declarative/fx/qfxborderimage.h b/src/declarative/fx/qfxborderimage.h index eae9bd1..5bc1067 100644 --- a/src/declarative/fx/qfxborderimage.h +++ b/src/declarative/fx/qfxborderimage.h @@ -59,8 +59,8 @@ class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase Q_ENUMS(TileMode) Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) - Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY tileModeChanged) - Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY tileModeChanged) + Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) + Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) public: QFxBorderImage(QFxItem *parent=0); @@ -80,7 +80,8 @@ public: void setSource(const QUrl &url); Q_SIGNALS: - void tileModeChanged(); + void horizontalTileModeChanged(); + void verticalTileModeChanged(); protected: QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index a8b27f4..2ed704e 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -1000,7 +1000,7 @@ void QFxGridView::setCellWidth(int cellWidth) if (cellWidth != d->cellWidth && cellWidth > 0) { d->cellWidth = qMax(1, cellWidth); d->updateGrid(); - emit cellSizeChanged(); + emit cellWidthChanged(); d->layout(); } } @@ -1017,7 +1017,7 @@ void QFxGridView::setCellHeight(int cellHeight) if (cellHeight != d->cellHeight && cellHeight > 0) { d->cellHeight = qMax(1, cellHeight); d->updateGrid(); - emit cellSizeChanged(); + emit cellHeightChanged(); d->layout(); } } diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 08a7565..7f30f03 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -67,8 +67,8 @@ class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable Q_PROPERTY(Flow flow READ flow WRITE setFlow) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) - Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellSizeChanged) - Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellSizeChanged) + Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged) + Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged) Q_CLASSINFO("DefaultProperty", "data") public: @@ -121,7 +121,8 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void currentIndexChanged(); - void cellSizeChanged(); + void cellWidthChanged(); + void cellHeightChanged(); protected: virtual void viewportMoved(); diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 1247021..aa8ccfd 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -1180,6 +1180,7 @@ void QFxListView::setOrientation(Qt::Orientation orientation) setViewportHeight(-1); d->clear(); refill(); + emit orientationChanged(); d->updateCurrent(d->currentIndex); } } diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 3cff422..5a83604 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(bool strictlyEnforceHighlightRange READ strictlyEnforceHighlightRange WRITE setStrictlyEnforceHighlightRange) Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) - Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged) @@ -106,7 +106,7 @@ public: bool strictlyEnforceHighlightRange() const; void setStrictlyEnforceHighlightRange(bool strict); - + qreal preferredHighlightBegin() const; void setPreferredHighlightBegin(qreal); @@ -144,6 +144,7 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void spacingChanged(); + void orientationChanged(); void currentIndexChanged(); void currentSectionChanged(); void sectionExpressionChanged(); diff --git a/src/declarative/fx/qfxpositioners.cpp b/src/declarative/fx/qfxpositioners.cpp index e4500aa..f8e7213 100644 --- a/src/declarative/fx/qfxpositioners.cpp +++ b/src/declarative/fx/qfxpositioners.cpp @@ -97,6 +97,7 @@ void QFxBasePositioner::setSpacing(int s) return; d->_spacing = s; prePositioning(); + emit spacingChanged(); } QmlTransition *QFxBasePositioner::move() const diff --git a/src/declarative/fx/qfxpositioners.h b/src/declarative/fx/qfxpositioners.h index 89a61d7..d62da08 100644 --- a/src/declarative/fx/qfxpositioners.h +++ b/src/declarative/fx/qfxpositioners.h @@ -59,7 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxBasePositioner : public QFxItem { Q_OBJECT - Q_PROPERTY(int spacing READ spacing WRITE setSpacing) + Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(QmlTransition *move READ move WRITE setMove) Q_PROPERTY(QmlTransition *add READ add WRITE setAdd) Q_PROPERTY(QmlTransition *remove READ remove WRITE setRemove) @@ -93,6 +93,7 @@ protected: Q_SIGNALS: void layoutItemChanged(); + void spacingChanged(); protected Q_SLOTS: virtual void doPositioning()=0; -- cgit v0.12 From 04511e3dbbcdf40489852babbf4753e0f744c26f Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 9 Oct 2009 14:25:22 +1000 Subject: Improve qdoc generated QML documentation. --- doc/src/declarative/elements.qdoc | 2 +- tools/qdoc3/config.h | 4 ++++ tools/qdoc3/cppcodemarker.cpp | 12 ++++++------ tools/qdoc3/doc.cpp | 4 ++++ tools/qdoc3/helpprojectwriter.cpp | 12 ++++++++++-- tools/qdoc3/node.cpp | 4 +++- tools/qdoc3/node.h | 2 ++ tools/qdoc3/test/qml.qdocconf | 5 ++++- 8 files changed, 34 insertions(+), 11 deletions(-) diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index cb30a6e..98c4ee1 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -40,7 +40,7 @@ ****************************************************************************/ /*! -\page elements.html +\page qmlelements.html \target elements \title QML Elements diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h index 07cdb59..725129a 100644 --- a/tools/qdoc3/config.h +++ b/tools/qdoc3/config.h @@ -162,6 +162,10 @@ class Config #define CONFIG_FILEEXTENSIONS "fileextensions" +#ifdef QDOC_QML +#define CONFIG_QMLONLY "qmlonly" +#endif + QT_END_NAMESPACE #endif diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index ed3d150..1062f9c 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -1109,15 +1109,15 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, if (qmlClassNode) { if (style == Summary) { FastSection qmlproperties(qmlClassNode, - "QML Properties", + "Properties", "property", "properties"); FastSection qmlsignals(qmlClassNode, - "QML Signals", + "Signals", "signal", "signals"); FastSection qmlmethods(qmlClassNode, - "QML Methods", + "Methods", "method", "methods"); @@ -1146,9 +1146,9 @@ QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, append(sections,qmlmethods); } else if (style == Detailed) { - FastSection qmlproperties(qmlClassNode,"QML Property Documentation"); - FastSection qmlsignals(qmlClassNode,"QML Signal Documentation"); - FastSection qmlmethods(qmlClassNode,"QML Method Documentation"); + FastSection qmlproperties(qmlClassNode, "Property Documentation"); + FastSection qmlsignals(qmlClassNode,"Signal Documentation"); + FastSection qmlmethods(qmlClassNode,"Method Documentation"); NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); while (c != qmlClassNode->childNodes().end()) { if ((*c)->subType() == Node::QmlPropertyGroup) { diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 748390f..f4931b8 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -2841,6 +2841,10 @@ void Doc::initialize(const Config& config) DocParser::sourceDirs = config.getStringList(CONFIG_SOURCEDIRS); DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION); +#ifdef QDOC_QML + QmlClassNode::qmlOnly = config.getBool(CONFIG_QMLONLY); +#endif + QStringMap reverseAliasMap; QSet commands = config.subVars(CONFIG_ALIAS); diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index 4973387..52f54c0 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -187,8 +187,16 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const details << node->parent()->name()+"::"+node->name(); } else if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); - details << fake->fullTitle(); - details << fake->fullTitle(); +#ifdef QDOC_QML + if (fake->subType() == Node::QmlClass) { + details << (QmlClassNode::qmlOnly ? fake->name() : fake->fullTitle()); + details << "QML." + fake->name(); + } else +#endif + { + details << fake->fullTitle(); + details << fake->fullTitle(); + } } else { details << node->name(); details << node->name(); diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index d547d20..42b73d9 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -1057,6 +1057,8 @@ bool TargetNode::isInnerNode() const } #ifdef QDOC_QML +bool QmlClassNode::qmlOnly = false; + /*! Constructor for the Qml class node. */ @@ -1065,7 +1067,7 @@ QmlClassNode::QmlClassNode(InnerNode *parent, const ClassNode* cn) : FakeNode(parent, name, QmlClass), cnode(cn) { - setTitle("QML " + name + " Element Reference"); + setTitle((qmlOnly ? "" : "QML ") + name + " Element Reference"); } /*! diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index 09f38d2..dfe882c 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -364,6 +364,8 @@ class QmlClassNode : public FakeNode const ClassNode* classNode() const { return cnode; } virtual QString fileBase() const; + static bool qmlOnly; + private: const ClassNode* cnode; }; diff --git a/tools/qdoc3/test/qml.qdocconf b/tools/qdoc3/test/qml.qdocconf index 3a7d76a..3b5d8dc 100644 --- a/tools/qdoc3/test/qml.qdocconf +++ b/tools/qdoc3/test/qml.qdocconf @@ -7,6 +7,7 @@ include(qt-defines.qdocconf) project = Qml description = Qml Reference Documentation url = http://doc.qtsoftware.com/4.6 +qmlonly = true edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \ QtXmlPatterns QtTest @@ -72,6 +73,8 @@ HTML.postheader = "  " \ "\n" \ "
" \ "" \ - "Home" \ + "Home ·" \ + " " \ + "Elements" \ "
" -- cgit v0.12 From 0dc2fe6685323a8aa6bc0e79f908aa9f2dafe6f2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 14:51:40 +1000 Subject: Output file/line for script errors --- src/declarative/qml/qmlbinding.cpp | 4 +- src/declarative/qml/qmlbinding.h | 3 +- src/declarative/qml/qmlcompiler.cpp | 18 ++++++-- src/declarative/qml/qmlcontext.cpp | 20 +++------ src/declarative/qml/qmlcontext_p.h | 3 +- src/declarative/qml/qmlexpression.cpp | 48 ++++++++++++++-------- src/declarative/qml/qmlexpression.h | 4 +- src/declarative/qml/qmlexpression_p.h | 4 +- src/declarative/qml/qmlinstruction_p.h | 2 + src/declarative/qml/qmlparser_p.h | 2 + src/declarative/qml/qmlvme.cpp | 7 ++-- .../declarative/qmlecmascript/data/scriptErrors.js | 2 + .../qmlecmascript/data/scriptErrors.qml | 10 +++++ .../qmlecmascript/tst_qmlecmascript.cpp | 20 +++++++++ 14 files changed, 102 insertions(+), 45 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptErrors.js create mode 100644 tests/auto/declarative/qmlecmascript/data/scriptErrors.qml diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 3a34f46..58ce02c 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -67,8 +67,8 @@ QmlBindingPrivate::QmlBindingPrivate() { } -QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) +QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent) +: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate) { setParent(parent); } diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index e3a297c..1c0ccf1 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -90,7 +90,8 @@ class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, Q_OBJECT public: QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0); - QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); + QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int, + QObject *parent); ~QmlBinding(); void setTarget(const QmlMetaProperty &); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 12e8101..5e6a8aa 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -833,6 +833,8 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction script; script.type = QmlInstruction::StoreScript; script.line = -1; // ### + script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii)); + script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii); script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); output->bytecode << script; } @@ -1054,6 +1056,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) { QString scriptCode; + QString sourceUrl; + int lineNumber = 1; if (script->properties.count() == 1 && script->properties.begin().key() == QByteArray("source")) { @@ -1066,8 +1070,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) source->values.at(0)->object || !source->values.at(0)->value.isString()) COMPILE_EXCEPTION(source, "Invalid Script source value"); - QString sourceUrl = - output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); + sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); for (int ii = 0; ii < unit->resources.count(); ++ii) { if (unit->resources.at(ii)->url == sourceUrl) { @@ -1079,10 +1082,14 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } else if (!script->properties.isEmpty()) { COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); } else if (script->defaultProperty) { + sourceUrl = output->url.toString(); + QmlParser::Location currentLocation; for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) { Value *v = script->defaultProperty->values.at(ii); + if (lineNumber == 1) + lineNumber = v->location.start.line; if (v->object || !v->value.isString()) COMPILE_EXCEPTION(v, "Invalid Script block"); @@ -1105,8 +1112,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } - if (!scriptCode.isEmpty()) + if (!scriptCode.isEmpty()) { obj->scriptBlocks.append(scriptCode); + obj->scriptBlocksFile.append(sourceUrl); + obj->scriptBlocksLineNumber.append(lineNumber); + } return true; } @@ -2322,7 +2332,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; - store.line = prop->location.end.line; + store.line = binding->location.start.line; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index f6795aa..3f61867 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -61,7 +61,8 @@ QmlContextPrivate::QmlContextPrivate() { } -void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) +void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, + const QString &fileName, int lineNumber) { if (!engine) return; @@ -78,21 +79,10 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); - QScriptValue val = scriptEngine->evaluate(script); + QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ - qWarning() << exception.property(QLatin1String("fileName")).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - - } else { - qmlInfo(scopeObject) << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + QmlExpressionPrivate::printException(scriptEngine); scriptEngine->popContext(); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index d18bfda..fe74e28 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -94,7 +94,8 @@ public: QScriptValue scriptValue; QList scripts; - void addScript(const QString &script, QObject *scope); + void addScript(const QString &script, QObject *scope, + const QString &fileName = QString(), int lineNumber = 1); QUrl url; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 23e1700..6a6ef5d 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -89,8 +89,11 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, - QObject *me) + QObject *me, const QUrl &url, int lineNumber) { + data->fileName = url.toString(); + data->line = lineNumber; + quint32 *exprData = (quint32 *)expr; Q_ASSERT(*exprData == BasicScriptEngineData || *exprData == PreTransformedQtScriptData); @@ -107,7 +110,8 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { - dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression)); + dd->programs[progIdx] = + new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } QmlContextPrivate *ctxtPriv = ctxt->d_func(); @@ -145,11 +149,12 @@ QmlExpression::QmlExpression() /*! \internal */ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me, + const QUrl &url, int lineNumber, QmlExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QmlExpression); - d->init(ctxt, expr, rc, me); + d->init(ctxt, expr, rc, me, url, lineNumber); } /*! @@ -251,6 +256,28 @@ QVariant QmlExpressionPrivate::evalSSE() return rv; } +void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine) +{ + if (scriptEngine->hasUncaughtException() && + scriptEngine->uncaughtException().isError()) { + + QString fileName; + int lineNumber = scriptEngine->uncaughtExceptionLineNumber(); + + QScriptValue exception = scriptEngine->uncaughtException(); + QLatin1String fileNameProp("fileName"); + + if (!exception.property(fileNameProp).toString().isEmpty()){ + fileName = exception.property(fileNameProp).toString(); + } else { + fileName = QLatin1String(""); + } + + qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": " + << qPrintable(exception.toString()); + } +} + QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -291,19 +318,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QScriptValue svalue = data->expressionFunction.call(); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - QLatin1String fileNameProp("fileName"); - if (!exception.property(fileNameProp).toString().isEmpty()){ - qWarning() << exception.property(fileNameProp).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - } else { - qWarning() << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + printException(scriptEngine); if (secondaryScope) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index c295a1c..b85e0a7 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -89,8 +89,8 @@ Q_SIGNALS: protected: QmlExpression(QmlContext *, const QString &, QObject *, QmlExpressionPrivate &dd); - QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, - QmlExpressionPrivate &dd); + QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &, + int, QmlExpressionPrivate &dd); private Q_SLOTS: void __q_notify(); diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 33016e6..d9bb27b 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -136,7 +136,7 @@ public: }; void init(QmlContext *, const QString &, QObject *); - void init(QmlContext *, void *, QmlRefCount *, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *, const QUrl &, int); QmlExpressionData *data; @@ -150,6 +150,8 @@ public: static QmlExpressionPrivate *get(QmlExpression *expr) { return static_cast(QObjectPrivate::get(expr)); } + + static void printException(QScriptEngine *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 1dcdace..0da40c3 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -240,6 +240,8 @@ public: } storeString; struct { int value; + int fileName; + int lineNumber; } storeScript; struct { int propertyIndex; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 16862eb..d05cc73 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -168,6 +168,8 @@ namespace QmlParser // Script blocks that were nested under this object QStringList scriptBlocks; + QStringList scriptBlocksFile; + QList scriptBlocksLineNumber; // The bytes to cast instances by to get to the QmlParserStatus // interface. -1 indicates the type doesn't support this interface. diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index e4eef64..a057f11 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -567,7 +567,9 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, case QmlInstruction::StoreScript: { QObject *target = stack.top(); - cp->addScript(primitives.at(instr.storeScript.value), target); + cp->addScript(primitives.at(instr.storeScript.value), target, + primitives.at(instr.storeScript.fileName), + instr.storeScript.lineNumber); } break; @@ -597,12 +599,11 @@ QObject *QmlVME::run(QStack &stack, QmlContext *ctxt, if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) break; - QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); bind->addToObject(target); - bind->setSourceLocation(comp->url, instr.line); } break; diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.js b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js new file mode 100644 index 0000000..1d7b357 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.js @@ -0,0 +1,2 @@ +// Comment +a = 10 diff --git a/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml new file mode 100644 index 0000000..3fb8ff7 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scriptErrors.qml @@ -0,0 +1,10 @@ +import Qt 4.6 + +Object { + Script { source: "scriptErrors.js" } + Script { function getValue() { a = 10; return 0; } } + + property int x: a.value + property int y: getValue(); +} + diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index dde3bb7..673be35 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -61,6 +61,7 @@ private slots: void objectToString(); void selfDeletingBinding(); void extendedObjectPropertyLookup(); + void scriptErrors(); private: QmlEngine engine; @@ -724,6 +725,25 @@ void tst_qmlecmascript::extendedObjectPropertyLookup() QVERIFY(object != 0); } +/* +Test file/lineNumbers for binding/Script errors. +*/ +void tst_qmlecmascript::scriptErrors() +{ + QmlComponent component(&engine, TEST_FILE("scriptErrors.qml")); + QString url = component.url().toString(); + + QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\""; + QString warning2 = url + ":7: TypeError: Result of expression 'a' [undefined] is not an object."; + QString warning3 = url + ":5: Error: Invalid write to global property \"a\""; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + QObject *object = component.create(); + QVERIFY(object != 0); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" -- cgit v0.12 From a6743af8705a93fb30e278dd634ff37597ddb627 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 15:40:03 +1000 Subject: Remove deprecated write to signal property support --- src/declarative/qml/qmlmetaproperty.cpp | 30 +----------------------------- src/declarative/qml/qmlmetaproperty_p.h | 2 -- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 302ce8c..a43f6c3 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -698,30 +698,6 @@ QVariant QmlMetaProperty::read() const return QVariant(); } -void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) -{ - QString expr = value.toString(); - const QObjectList &children = object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == core.coreIndex) { - if (expr.isEmpty()) { - sig->disconnect(); - sig->deleteLater(); - } else { - sig->expression()->setExpression(expr); - } - return; - } - } - - if (!expr.isEmpty()) { - // XXX scope - (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object); - } -} - QVariant QmlMetaPropertyPrivate::readValueProperty() { uint type = q->type(); @@ -963,11 +939,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const if (!d->object) return; - if (type() & SignalProperty) { - - d->writeSignalProperty(value); - - } else if (d->core.isValid()) { + if (type() & Property && d->core.isValid()) { d->writeValueProperty(value, source); diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 00b9c3a..4576b71 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -96,8 +96,6 @@ public: int propertyType() const; QmlMetaProperty::PropertyCategory propertyCategory() const; - void writeSignalProperty(const QVariant &); - QVariant readValueProperty(); void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); -- cgit v0.12 From 89a5a33d5643eb31bb44adce8a8fd65986d76c20 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 15:56:36 +1000 Subject: Fixes yahoonews.qml Task-number: QT-2281 --- examples/declarative/xmldata/yahoonews.qml | 146 ++++++++++++----------------- 1 file changed, 60 insertions(+), 86 deletions(-) diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml index 6d43f46..7d8b8a2 100644 --- a/examples/declarative/xmldata/yahoonews.qml +++ b/examples/declarative/xmldata/yahoonews.qml @@ -5,100 +5,74 @@ Rectangle { GradientStop { position: 0; color: "black" } GradientStop { position: 1.0; color: "#AAAAAA" } } - width: 600 - height: 600 - resources: [ - XmlListModel { - id: feedModel - source: "http://rss.news.yahoo.com/rss/oceania" - query: "/rss/channel/item" - XmlRole { - name: "title" - query: "title/string()" - } - XmlRole { - name: "link" - query: "link/string()" - } - XmlRole { - name: "description" - query: "description/string()" + width: 600; height: 600 + + XmlListModel { + id: feedModel + source: "http://rss.news.yahoo.com/rss/oceania" + query: "/rss/channel/item" + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "link"; query: "link/string()" } + XmlRole { name: "description"; query: "description/string()" } + } + + Component { + id: feedDelegate + Item { + id: delegate + height: wrapper.height + 10 + + MouseRegion { + anchors.fill: wrapper + onPressed: delegate.ListView.view.currentIndex = index; + onClicked: if (wrapper.state == 'Details') wrapper.state = ''; else wrapper.state = 'Details'; } - }, - Component { - id: feedDelegate - Item { - id: delegate - height: wrapper.height + 10 - MouseRegion { - anchors.fill: wrapper - onPressed: { delegate.ListView.view.currentIndex = index; } - onClicked: { if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';} } + + Rectangle { + id: wrapper + y: 5; height: titleText.height + 10; width: 580 + color: "#F0F0F0"; radius: 5 + Text { + id: titleText + x: 10; y: 5 + text: '' + title + '' + font.bold: true; font.family: "Helvetica"; font.pointSize: 14 + onLinkActivated: { print('link clicked: ' + link) } } - Rectangle { - id: wrapper - y: 5 - height: titleText.height + 10 - width: 580 - color: "#F0F0F0" - radius: 5 - Text { - x: 10 - y: 5 - id: titleText - text: '' + title + '' - font.bold: true - font.family: "Helvetica" - font.pointSize: 14 - onLinkActivated: { print('link clicked: ' + link) } - } - Text { - x: 10 - id: description - text: description - width: 560 - wrap: true - font.family: "Helvetica" - anchors.top: titleText.bottom - anchors.topMargin: 5 - opacity: 0 + + Text { + x: 10 + id: descriptionText + text: description + width: 560 + wrap: true + font.family: "Helvetica" + anchors.top: titleText.bottom + anchors.topMargin: 5 + opacity: 0 + } + + states: State { + name: "Details" + PropertyChanges { target: wrapper; height: childrenRect.height + 10 } + PropertyChanges { target: descriptionText; opacity: 1 } + } + + transitions: Transition { + from: "*"; to: "Details"; reversible: true + SequentialAnimation { + NumberAnimation { duration: 200; properties: "height"; easing: "easeOutQuad" } + NumberAnimation { duration: 200; properties: "opacity" } } - states: [ - State { - name: "Details" - PropertyChanges { target: wrapper; height: childrenRect.height + 10 } - PropertyChanges { target: description; opacity: 1 } - } - ] - transitions: [ - Transition { - from: "*" - to: "Details" - reversible: true - SequentialAnimation { - NumberAnimation { - duration: 200 - properties: "height" - easing: "easeOutQuad" - } - NumberAnimation { - duration: 200 - properties: "opacity" - } - } - } - ] } } } - ] + } + ListView { id: list - x: 10 - y: 10 - width: parent.width - 20 - height: parent.height - 20 - clip: true + x: 10; y: 10 + width: parent.width - 20; height: parent.height - 20 model: feedModel delegate: feedDelegate } -- cgit v0.12 From e20dabec726b44cbe4e3078699932c59979cb977 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 16:42:14 +1000 Subject: Tweak scope ordering (again) ids and methods shadow properties. The reasoning is that the user explicitly declared these names, whereas they might not even know a property by that name exists. --- src/declarative/qml/qmlcontext.cpp | 11 ++--- src/declarative/qml/qmlcontext_p.h | 2 - src/declarative/qml/qmlcontextscriptclass.cpp | 57 +++++++++++++++------- src/declarative/qml/qmlcontextscriptclass_p.h | 6 ++- src/declarative/qml/qmlexpression.cpp | 10 +--- .../declarative/qmlecmascript/data/scope.2.qml | 42 ++++++++++++++++ .../qmlecmascript/tst_qmlecmascript.cpp | 41 +++++++++++----- 7 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/scope.2.qml diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 3f61867..43a4741 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -64,6 +64,8 @@ QmlContextPrivate::QmlContextPrivate() void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, const QString &fileName, int lineNumber) { + Q_Q(QmlContext); + if (!engine) return; @@ -71,11 +73,8 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(scriptValue); + scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - if (scopeObject) - scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); - QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); @@ -129,10 +128,6 @@ void QmlContextPrivate::init() if (parent) parent->d_func()->childContexts.insert(q); - - //set scope chain - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index fe74e28..9a77e94 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -91,8 +91,6 @@ public: QObjectList defaultObjects; int highPriorityCount; - QScriptValue scriptValue; - QList scripts; void addScript(const QString &script, QObject *scope, const QString &fileName = QString(), int lineNumber = 1); diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 6d2c58c..939d008 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -47,8 +47,9 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { - ContextData(QmlContext *c) : context(c) {} + ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {} QGuard context; + QGuard scopeObject; }; /* @@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass() { } -QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) @@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) return data->context; } -#include QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastScopeObject = 0; lastContext = 0; lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; QmlContext *bindContext = ((ContextData *)object)->context.data(); + QObject *scopeObject = ((ContextData *)object)->scopeObject.data(); if (!bindContext) return 0; while (bindContext) { - QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + QScriptClass::QueryFlags rv = + queryProperty(bindContext, scopeObject, name, flags); + scopeObject = 0; // Only applies to the first context if (rv) return rv; bindContext = bindContext->parentContext(); } @@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, +QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject, + const Identifier &name, QScriptClass::QueryFlags flags) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) { + lastContext = bindContext; + return QScriptClass::HandlesReadAccess; + } + } + + if (scopeObject) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(scopeObject, name, flags, 0); + if (rv) { + lastScopeObject = scopeObject; + lastContext = bindContext; + return rv; + } + } + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); @@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } return 0; } @@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + if (lastScopeObject) { - if (lastData) { + return ep->objectClass->property(lastScopeObject, name); + + } else if (lastData) { if (lastData->type) return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); @@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - Q_ASSERT(lastDefaultObject != -1); + Q_ASSERT(lastScopeObject || lastDefaultObject != -1); QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); @@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + if (lastScopeObject) { + ep->objectClass->setProperty(lastScopeObject, name, value); + } else { + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 761a115..126c8fe 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -67,7 +67,7 @@ public: QmlContextScriptClass(QmlEngine *); ~QmlContextScriptClass(); - QScriptValue newContext(QmlContext *); + QScriptValue newContext(QmlContext *, QObject * = 0); QmlContext *contextFromValue(const QScriptValue &); @@ -78,11 +78,13 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject, + const Identifier &, QScriptClass::QueryFlags flags); QmlEngine *engine; + QObject *lastScopeObject; QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 6a6ef5d..0de64d9 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -114,11 +114,8 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } - QmlContextPrivate *ctxtPriv = ctxt->d_func(); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); @@ -297,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - - if (data->me) - scriptContext->pushScope(ep->objectClass->newQObject(data->me)); + scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me)); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, diff --git a/tests/auto/declarative/qmlecmascript/data/scope.2.qml b/tests/auto/declarative/qmlecmascript/data/scope.2.qml new file mode 100644 index 0000000..433a22e --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scope.2.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Item { + property int a: 0 + property int b: 0 + + Script { + function b() { return 11; } + function c() { return 33; } + } + + Object { + id: a + property int value: 19 + } + + Object { + id: c + property int value: 24 + } + + Object { + id: nested + property int a: 1 + property int test: a.value + property int test2: b() + property int test3: c.value + } + + + // id takes precedence over local, and root properties + property int test1: a.value + property alias test2: nested.test + + // methods takes precedence over local, and root properties + property int test3: b() + property alias test4: nested.test2 + + // id takes precedence over methods + property int test5: c.value + property alias test6: nested.test3 +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 673be35..5e04f7c 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -538,20 +538,35 @@ void tst_qmlecmascript::nonExistantAttachedObject() void tst_qmlecmascript::scope() { - QmlComponent component(&engine, TEST_FILE("scope.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + { + QmlComponent component(&engine, TEST_FILE("scope.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 1); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toString(), QString("1Test")); + QCOMPARE(object->property("test4").toString(), QString("2Test")); + QCOMPARE(object->property("test5").toInt(), 1); + QCOMPARE(object->property("test6").toInt(), 1); + QCOMPARE(object->property("test7").toInt(), 2); + QCOMPARE(object->property("test8").toInt(), 2); + QCOMPARE(object->property("test9").toInt(), 1); + QCOMPARE(object->property("test10").toInt(), 3); + } + + { + QmlComponent component(&engine, TEST_FILE("scope.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); - QCOMPARE(object->property("test1").toInt(), 1); - QCOMPARE(object->property("test2").toInt(), 2); - QCOMPARE(object->property("test3").toString(), QString("1Test")); - QCOMPARE(object->property("test4").toString(), QString("2Test")); - QCOMPARE(object->property("test5").toInt(), 1); - QCOMPARE(object->property("test6").toInt(), 1); - QCOMPARE(object->property("test7").toInt(), 2); - QCOMPARE(object->property("test8").toInt(), 2); - QCOMPARE(object->property("test9").toInt(), 1); - QCOMPARE(object->property("test10").toInt(), 3); + QCOMPARE(object->property("test1").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 19); + QCOMPARE(object->property("test3").toInt(), 11); + QCOMPARE(object->property("test4").toInt(), 11); + QCOMPARE(object->property("test5").toInt(), 24); + QCOMPARE(object->property("test6").toInt(), 24); + } } /* -- cgit v0.12 From 8a88e6cf15636b0adaf5547e5fa883e9631ae1cb Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 16:49:06 +1000 Subject: fixes gridview.qml Task-number: QT-2271 --- examples/declarative/gridview/gridview.qml | 52 +++++++++--------------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/examples/declarative/gridview/gridview.qml b/examples/declarative/gridview/gridview.qml index 2e5110a..93931c7 100644 --- a/examples/declarative/gridview/gridview.qml +++ b/examples/declarative/gridview/gridview.qml @@ -4,57 +4,35 @@ Rectangle { width: 300; height: 400; color: "white" ListModel { - id: AppModel - ListElement { - name: "Music" - icon: "AudioPlayer_48.png" - } - ListElement { - name: "Movies" - icon: "VideoPlayer_48.png" - } - ListElement { - name: "Camera" - icon: "Camera_48.png" - } - ListElement { - name: "Calendar" - icon: "DateBook_48.png" - } - ListElement { - name: "Messaging" - icon: "EMail_48.png" - } - ListElement { - name: "Todo List" - icon: "TodoList_48.png" - } - ListElement { - name: "Contacts" - icon: "AddressBook_48.png" - } + id: appModel + ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" } + ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" } + ListElement { name: "Camera"; icon: "pics/Camera_48.png" } + ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" } + ListElement { name: "Messaging"; icon: "pics/EMail_48.png" } + ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" } + ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" } } Component { - id: AppDelegate + id: appDelegate Item { width: 100; height: 100 - Image { id: Icon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon } - Text { anchors.top: Icon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name } + Image { id: myIcon; y: 20; anchors.horizontalCenter: parent.horizontalCenter; source: icon } + Text { anchors.top: myIcon.bottom; anchors.horizontalCenter: parent.horizontalCenter; text: name } } } Component { - id: AppHighlight - Rectangle { width: 80; height: 80; color: "#FFFF88" } + id: appHighlight + Rectangle { width: 80; height: 80; color: "lightsteelblue" } } GridView { - id: List1 anchors.fill: parent cellWidth: 100; cellHeight: 100 - model: AppModel; delegate: AppDelegate - highlight: AppHighlight + model: appModel; delegate: appDelegate + highlight: appHighlight focus: true } } -- cgit v0.12 From c1e591809975119d87d3f2d7fdb33eda22f0ccd1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 17:02:04 +1000 Subject: Fix snow demo --- examples/declarative/snow/ImageBatch.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/declarative/snow/ImageBatch.qml b/examples/declarative/snow/ImageBatch.qml index 62f986c..86e11f7 100644 --- a/examples/declarative/snow/ImageBatch.qml +++ b/examples/declarative/snow/ImageBatch.qml @@ -35,14 +35,14 @@ GridView { XmlRole { name: "url"; query: "media:content/@url/string()" } } - Item { + delegate: Item { id: root property bool isSelected: GridView.isCurrentItem && grid.isSelected transformOrigin: "Center" width: grid.imageWidth; height: grid.imageHeight; Image { id: flickrImage; source: url; fillMode: "PreserveAspectFit"; smooth: true; anchors.fill: parent; - opacity: (status == 1)?1:0; opacity: Behavior { NumberAnimation { properties: "opacity" } } } + opacity: (status == Image.Ready)?1:0; /*opacity: Behavior { NumberAnimation { properties: "opacity" } }*/ } Loading { anchors.centerIn: parent; visible: flickrImage.status!=1 } states: State { -- cgit v0.12 From 165785ed7ad463100e144467a09708742259836c Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 9 Oct 2009 17:08:03 +1000 Subject: Do not use 'resources:' in examples --- examples/declarative/listview/recipes.qml | 228 ++++++++++++------------ examples/declarative/webview/newwindows.qml | 33 ++-- examples/declarative/xmldata/daringfireball.qml | 81 ++++----- 3 files changed, 168 insertions(+), 174 deletions(-) diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml index 4ccb344..3410f56 100644 --- a/examples/declarative/listview/recipes.qml +++ b/examples/declarative/listview/recipes.qml @@ -1,128 +1,136 @@ import Qt 4.6 - import "content" + // This example illustrates expanding a list item to show a more detailed view + Rectangle { id: page width: 400; height: 240; color: "black" - resources: [ - // Delegate for the recipes. This delegate has two modes: - // 1. the list mode (default), which just shows the picture and title of the recipe. - // 2. the details mode, which also shows the ingredients and method. - Component { - id: recipeDelegate - Item { - id: wrapper - width: list.width - // Create a property to contain the visibility of the details. - // We can bind multiple element's opacity to this one property, - // rather than having a "PropertyChanges" line for each element we - // want to fade. - property real detailsOpacity : 0 - - // A simple rounded rectangle for the background - Rectangle { - id: background - x: 1; y: 2; width: parent.width-2; height: parent.height-4 - color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5 - } - // This mouse region covers the entire delegate. - // When clicked it changes mode to 'Details'. If we are already - // in Details mode, then no change will happen. - MouseRegion { - id: pageMouse - anchors.fill: parent - onClicked: { wrapper.state = 'Details' } - } - // Layout the page. Picture, title and ingredients at the top, method at the - // bottom. Note that elements that should not be visible in the list - // mode have their opacity set to wrapper.detailsOpacity. - Row { - id: topLayout - x: 10; y: 10; height: recipePic.height; width: parent.width - spacing: 10 - Image { - id: recipePic - source: picture; width: 48; height: 48 - } - Column { - height: recipePic.height; width: background.width-recipePic.width-20 - spacing: 5 - Text { id: name; text: title; font.bold: true; font.pointSize: 16 } - Text { - text: "Ingredients"; font.pointSize: 12; font.bold: true - opacity: wrapper.detailsOpacity - } - Text { - text: ingredients; wrap: true; width: parent.width - opacity: wrapper.detailsOpacity - } - } + + // Delegate for the recipes. This delegate has two modes: + // 1. the list mode (default), which just shows the picture and title of the recipe. + // 2. the details mode, which also shows the ingredients and method. + Component { + id: recipeDelegate + Item { + id: wrapper + width: list.width + + // Create a property to contain the visibility of the details. + // We can bind multiple element's opacity to this one property, + // rather than having a "PropertyChanges" line for each element we + // want to fade. + property real detailsOpacity : 0 + + // A simple rounded rectangle for the background + Rectangle { + id: background + x: 1; y: 2; width: parent.width - 2; height: parent.height - 4 + color: "#FEFFEE"; border.color: "#FFBE4F"; radius: 5 + } + + // This mouse region covers the entire delegate. + // When clicked it changes mode to 'Details'. If we are already + // in Details mode, then no change will happen. + MouseRegion { + id: pageMouse + anchors.fill: parent + onClicked: wrapper.state = 'Details'; + } + + // Layout the page. Picture, title and ingredients at the top, method at the + // bottom. Note that elements that should not be visible in the list + // mode have their opacity set to wrapper.detailsOpacity. + Row { + id: topLayout + x: 10; y: 10; height: recipePic.height; width: parent.width + spacing: 10 + + Image { + id: recipePic + source: picture; width: 48; height: 48 } - Item { - id: details - x: 10; width: parent.width-20 - anchors.top: topLayout.bottom; anchors.topMargin: 10 - anchors.bottom: parent.bottom; anchors.bottomMargin: 10 - opacity: wrapper.detailsOpacity + + Column { + height: recipePic.height; width: background.width-recipePic.width-20 + spacing: 5 + Text { id: name; text: title; font.bold: true; font.pointSize: 16 } Text { - id: methodTitle - text: "Method"; font.pointSize: 12; font.bold: true - anchors.top: parent.top - } - Flickable { - id: flick - anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom - width: parent.width; viewportHeight: methodText.height; clip: true - Text { id: methodText; text: method; wrap: true; width: details.width } - } - Image { - anchors.right: flick.right; anchors.top: flick.top - source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1 + text: "Ingredients"; font.pointSize: 12; font.bold: true + opacity: wrapper.detailsOpacity } - Image { - anchors.right: flick.right; anchors.bottom: flick.bottom - source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1 + Text { + text: ingredients; wrap: true; width: parent.width + opacity: wrapper.detailsOpacity } } - // A button to close the detailed view, i.e. set the state back to default (''). - MediaButton { - anchors.right: background.right; anchors.rightMargin: 5 - y: 10; opacity: wrapper.detailsOpacity - text: "Close"; onClicked: { wrapper.state = '' } + } + + Item { + id: details + x: 10; width: parent.width-20 + anchors.top: topLayout.bottom; anchors.topMargin: 10 + anchors.bottom: parent.bottom; anchors.bottomMargin: 10 + opacity: wrapper.detailsOpacity + + Text { + id: methodTitle + text: "Method"; font.pointSize: 12; font.bold: true + anchors.top: parent.top + } + Flickable { + id: flick + anchors.top: methodTitle.bottom; anchors.bottom: parent.bottom + width: parent.width; viewportHeight: methodText.height; clip: true + Text { id: methodText; text: method; wrap: true; width: details.width } } - // Make the default height equal the hight of the picture, plus margin. - height: 68 - states: [ - State { - name: "Details" - PropertyChanges { target: background; color: "white" } - // Make the picture bigger - PropertyChanges { target: recipePic; width: 128; height: 128 } - // Make details visible - PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 } - // Make the detailed view fill the entire list area - PropertyChanges { target: wrapper; height: list.height } - // Move the list so that this item is at the top. - PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y } - // Disallow flicking while we're in detailed view - PropertyChanges { target: wrapper.ListView.view; interactive: false } - } - ] - transitions: [ - Transition { - // Make the state changes smooth - ParallelAnimation { - ColorAnimation { property: "color"; duration: 500 } - NumberAnimation { - duration: 300; properties: "detailsOpacity,x,viewportY,height,width" - } - } + Image { + anchors.right: flick.right; anchors.top: flick.top + source: "content/pics/moreUp.png"; opacity: flick.atYBeginning ? 0 : 1 + } + Image { + anchors.right: flick.right; anchors.bottom: flick.bottom + source: "content/pics/moreDown.png"; opacity: flick.atYEnd ? 0 : 1 + } + } + + // A button to close the detailed view, i.e. set the state back to default (''). + MediaButton { + anchors.right: background.right; anchors.rightMargin: 5 + y: 10; opacity: wrapper.detailsOpacity + text: "Close"; onClicked: wrapper.state = ''; + } + + // Make the default height equal the hight of the picture, plus margin. + height: 68 + + states: State { + name: "Details" + PropertyChanges { target: background; color: "white" } + // Make the picture bigger + PropertyChanges { target: recipePic; width: 128; height: 128 } + // Make details visible + PropertyChanges { target: wrapper; detailsOpacity: 1; x: 0 } + // Make the detailed view fill the entire list area + PropertyChanges { target: wrapper; height: list.height } + // Move the list so that this item is at the top. + PropertyChanges { target: wrapper.ListView.view; explicit: true; viewportY: wrapper.y } + // Disallow flicking while we're in detailed view + PropertyChanges { target: wrapper.ListView.view; interactive: false } + } + + transitions: Transition { + // Make the state changes smooth + ParallelAnimation { + ColorAnimation { property: "color"; duration: 500 } + NumberAnimation { + duration: 300; properties: "detailsOpacity,x,viewportY,height,width" } - ] + } } } - ] + } + // The actual list ListView { id: list diff --git a/examples/declarative/webview/newwindows.qml b/examples/declarative/webview/newwindows.qml index 59e3b3e..e2ed58f 100644 --- a/examples/declarative/webview/newwindows.qml +++ b/examples/declarative/webview/newwindows.qml @@ -7,22 +7,23 @@ import Qt 4.6 Row { id: pages - height: 200 - resources: [ - Component { - id: webViewPage - Rectangle { - width: webView.width - height: webView.height - WebView { - id: webView - newWindowComponent: webViewPage - newWindowParent: pages - url: "newwindows.html" - } - } + height: 200; width: 500 + + Component { + id: webViewPage + Rectangle { + width: webView.width + height: webView.height + border.color: "gray" + + WebView { + id: webView + newWindowComponent: webViewPage + newWindowParent: pages + url: "newwindows.html" + } } - ] - width: 500 + } + Loader { sourceComponent: webViewPage } } diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml index bea38c8..938bdd5 100644 --- a/examples/declarative/xmldata/daringfireball.qml +++ b/examples/declarative/xmldata/daringfireball.qml @@ -2,59 +2,44 @@ import Qt 4.6 Rectangle { color: "white" - width: 600 - height: 600 - resources: [ - XmlListModel { - id: feedModel - source: "http://daringfireball.net/index.xml" - query: "/feed/entry" - namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" - XmlRole { - name: "title" - query: "title/string()" - } - XmlRole { - name: "tagline" - query: "author/name/string()" + width: 600; height: 600 + + XmlListModel { + id: feedModel + source: "http://daringfireball.net/index.xml" + query: "/feed/entry" + namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';" + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "tagline"; query: "author/name/string()" } + XmlRole { name: "content"; query: "content/string()" } + } + + Component { + id: feedDelegate + Item { + height: childrenRect.height + 20 + Text { + id: titleText + x: 10 + text: title; font.bold: true } - XmlRole { - name: "content" - query: "content/string()" + Text { + text: 'by ' + tagline + anchors.left: titleText.right; anchors.leftMargin: 10 + font.italic: true } - }, - Component { - id: feedDelegate - Item { - height: childrenRect.height + 20 - Text { - x: 10 - id: titleText - text: title - font.bold: true - } - Text { - text: 'by ' + tagline - anchors.left: titleText.right - anchors.leftMargin: 10 - font.italic: true - } - Text { - x: 10 - text: content - anchors.top: titleText.bottom - width: 580 - wrap: true - onLinkActivated: { print('link clicked: ' + link) } - } + Text { + x: 10 + text: content + anchors.top: titleText.bottom + width: 580; wrap: true + onLinkActivated: { print('link clicked: ' + link) } } } - ] + } + ListView { - id: list anchors.fill: parent - clip: true - model: feedModel - delegate: feedDelegate + model: feedModel; delegate: feedDelegate } } -- cgit v0.12 From 3b3213679a35cdfb1eedcd5b27e6c40f1eca45fd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Oct 2009 18:32:30 +1000 Subject: Support aliases to enum properties --- src/declarative/qml/qmlcompiler.cpp | 7 +++++-- tests/auto/declarative/qmllanguage/data/Alias2.qml | 9 +++++++++ tests/auto/declarative/qmllanguage/data/alias.4.qml | 6 ++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 9 +++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/Alias2.qml create mode 100644 tests/auto/declarative/qmllanguage/data/alias.4.qml diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 5e6a8aa..8856892 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -2253,10 +2253,13 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); + const char *typeName = aliasProperty.typeName(); + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, aliasProperty.typeName(), - builder.methodCount() - 1); + builder.addProperty(prop.name, typeName, builder.methodCount() - 1); propBuilder.setScriptable(true); return true; } diff --git a/tests/auto/declarative/qmllanguage/data/Alias2.qml b/tests/auto/declarative/qmllanguage/data/Alias2.qml new file mode 100644 index 0000000..b7e81a5 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/Alias2.qml @@ -0,0 +1,9 @@ +import Test 1.0 +import Qt 4.6 + +Object { + property var other + other: MyTypeObject { id: obj } + property alias enumAlias: obj.enumProperty; +} + diff --git a/tests/auto/declarative/qmllanguage/data/alias.4.qml b/tests/auto/declarative/qmllanguage/data/alias.4.qml new file mode 100644 index 0000000..bd6a769 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/alias.4.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +Alias2 { + enumAlias: MyTypeObject.EnumVal2 +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 3825b62..135a207 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -612,6 +612,15 @@ void tst_qmllanguage::aliasProperties() delete object; } + // Enum aliases + { + QmlComponent component(&engine, TEST_FILE("alias.4.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("enumAlias").toInt(), 1); + } } class TestType : public QObject { -- cgit v0.12 From 76448b41bb9c6212d2534f0597f9973c881c77bd Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 9 Oct 2009 12:11:15 +0200 Subject: Fix build --- src/declarative/qml/qmlpropertycache_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index f1b1219..91b0c53 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -132,7 +132,7 @@ QmlPropertyCache::Data::Data() { } -bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other) +bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other) { return flags == other.flags && propType == other.propType && -- cgit v0.12