From 5013d53d9400f61699f8edb1dc20f06e19a26a3d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Mar 2012 14:25:50 +0100 Subject: Move binding and expression classes to separate files Change-Id: Ia9c6996a606e140f31681ecd26d93b1b0fdedf02 Reviewed-by: Roberto Raggi --- src/qml/qml/qml.pri | 12 +- src/qml/qml/qqmlabstractbinding.cpp | 193 +++++++++++++++++++++ src/qml/qml/qqmlabstractbinding_p.h | 131 ++++++++++++++ src/qml/qml/qqmlabstractexpression.cpp | 101 +++++++++++ src/qml/qml/qqmlabstractexpression_p.h | 124 ++++++++++++++ src/qml/qml/qqmlbinding.cpp | 235 ------------------------- src/qml/qml/qqmlbinding_p.h | 99 +---------- src/qml/qml/qqmlexpression.cpp | 266 ---------------------------- src/qml/qml/qqmlexpression_p.h | 276 +----------------------------- src/qml/qml/qqmljavascriptexpression.cpp | 260 ++++++++++++++++++++++++++++ src/qml/qml/qqmljavascriptexpression_p.h | 274 +++++++++++++++++++++++++++++ src/qml/qml/qqmlproperty.cpp | 1 + src/qml/qml/qqmlvaluetypeproxybinding.cpp | 138 +++++++++++++++ src/qml/qml/qqmlvaluetypeproxybinding_p.h | 91 ++++++++++ src/qml/qml/qqmlvme.cpp | 1 + 15 files changed, 1333 insertions(+), 869 deletions(-) create mode 100644 src/qml/qml/qqmlabstractbinding.cpp create mode 100644 src/qml/qml/qqmlabstractbinding_p.h create mode 100644 src/qml/qml/qqmlabstractexpression.cpp create mode 100644 src/qml/qml/qqmlabstractexpression_p.h create mode 100644 src/qml/qml/qqmljavascriptexpression.cpp create mode 100644 src/qml/qml/qqmljavascriptexpression_p.h create mode 100644 src/qml/qml/qqmlvaluetypeproxybinding.cpp create mode 100644 src/qml/qml/qqmlvaluetypeproxybinding_p.h diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 0ce7c7ed5c..763a260b54 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -47,7 +47,11 @@ SOURCES += \ $$PWD/qqmlimport.cpp \ $$PWD/qqmllist.cpp \ $$PWD/qqmllocale.cpp \ - $$PWD/qlistmodelinterface.cpp + $$PWD/qlistmodelinterface.cpp \ + $$PWD/qqmlabstractexpression.cpp \ + $$PWD/qqmljavascriptexpression.cpp \ + $$PWD/qqmlabstractbinding.cpp \ + $$PWD/qqmlvaluetypeproxybinding.cpp \ HEADERS += \ $$PWD/qqmlglobal_p.h \ @@ -116,7 +120,11 @@ HEADERS += \ $$PWD/qqmlscriptstring_p.h \ $$PWD/qqmllocale_p.h \ $$PWD/qlistmodelinterface_p.h \ - $$PWD/qqmlcomponentattached_p.h + $$PWD/qqmlcomponentattached_p.h \ + $$PWD/qqmlabstractexpression_p.h \ + $$PWD/qqmljavascriptexpression_p.h \ + $$PWD/qqmlabstractbinding_p.h \ + $$PWD/qqmlvaluetypeproxybinding_p.h \ include(parser/parser.pri) include(rewriter/rewriter.pri) diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp new file mode 100644 index 0000000000..11e4ed2ed8 --- /dev/null +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlabstractbinding_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QQmlAbstractBinding::QQmlAbstractBinding() +: m_prevBinding(0), m_nextBinding(0) +{ +} + +QQmlAbstractBinding::~QQmlAbstractBinding() +{ + Q_ASSERT(m_prevBinding == 0); + Q_ASSERT(*m_mePtr == 0); +} + +/*! +Destroy the binding. Use this instead of calling delete. + +Bindings are free to implement their own memory management, so the delete operator is not +necessarily safe. The default implementation clears the binding, removes it from the object +and calls delete. +*/ +void QQmlAbstractBinding::destroy() +{ + removeFromObject(); + clear(); + + delete this; +} + +/*! +Add this binding to \a object. + +This transfers ownership of the binding to the object, marks the object's property as +being bound. + +However, it does not enable the binding itself or call update() on it. +*/ +void QQmlAbstractBinding::addToObject() +{ + Q_ASSERT(!m_prevBinding); + + QObject *obj = object(); + Q_ASSERT(obj); + + int index = propertyIndex(); + + QQmlData *data = QQmlData::get(obj, true); + + if (index & 0xFF000000) { + // Value type + + int coreIndex = index & 0xFFFFFF; + + // Find the value type proxy (if there is one) + QQmlValueTypeProxyBinding *proxy = 0; + if (data->hasBindingBit(coreIndex)) { + QQmlAbstractBinding *b = data->bindings; + while (b && b->propertyIndex() != coreIndex) + b = b->m_nextBinding; + Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy); + proxy = static_cast(b); + } + + if (!proxy) { + proxy = new QQmlValueTypeProxyBinding(obj, coreIndex); + + Q_ASSERT(proxy->propertyIndex() == coreIndex); + Q_ASSERT(proxy->object() == obj); + + proxy->addToObject(); + } + + m_nextBinding = proxy->m_bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &proxy->m_bindings; + proxy->m_bindings = this; + + } else { + m_nextBinding = data->bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &data->bindings; + data->bindings = this; + + data->setBindingBit(obj, index); + } +} + +/*! +Remove the binding from the object. +*/ +void QQmlAbstractBinding::removeFromObject() +{ + if (m_prevBinding) { + int index = propertyIndex(); + + *m_prevBinding = m_nextBinding; + if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; + m_prevBinding = 0; + m_nextBinding = 0; + + if (index & 0xFF000000) { + // Value type - we don't remove the proxy from the object. It will sit their happily + // doing nothing until it is removed by a write, a binding change or it is reused + // to hold more sub-bindings. + } else if (QObject *obj = object()) { + QQmlData *data = QQmlData::get(obj, false); + if (data) data->clearBindingBit(index); + } + } +} + +static void bindingDummyDeleter(QQmlAbstractBinding *) +{ +} + +QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer() +{ + if (m_mePtr.value().isNull()) + m_mePtr.value() = QSharedPointer(this, bindingDummyDeleter); + + return m_mePtr.value().toWeakRef(); +} + +void QQmlAbstractBinding::clear() +{ + if (!m_mePtr.isNull()) { + **m_mePtr = 0; + m_mePtr = 0; + } +} + +void QQmlAbstractBinding::retargetBinding(QObject *, int) +{ + qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding."); +} + +QString QQmlAbstractBinding::expression() const +{ + return QLatin1String(""); +} + +void QQmlAbstractBinding::setEnabled(bool enabled, QQmlPropertyPrivate::WriteFlags flags) +{ + if (enabled) update(flags); +} + + +QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h new file mode 100644 index 0000000000..d226e177bd --- /dev/null +++ b/src/qml/qml/qqmlabstractbinding_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLABSTRACTBINDING_P_H +#define QQMLABSTRACTBINDING_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 +#include + +QT_BEGIN_NAMESPACE + +class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding +{ +public: + typedef QWeakPointer Pointer; + + QQmlAbstractBinding(); + + virtual void destroy(); + + virtual QString expression() const; + + enum Type { PropertyBinding, ValueTypeProxy }; + virtual Type bindingType() const { return PropertyBinding; } + + // Should return the encoded property index for the binding. Should return this value + // even if the binding is not enabled or added to an object. + // Encoding is: coreIndex | (valueTypeIndex << 24) + virtual int propertyIndex() const = 0; + // Should return the object for the binding. Should return this object even if the + // binding is not enabled or added to the object. + virtual QObject *object() const = 0; + + void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); } + virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags) = 0; + + void update() { update(QQmlPropertyPrivate::DontRemoveBinding); } + virtual void update(QQmlPropertyPrivate::WriteFlags) = 0; + + void addToObject(); + void removeFromObject(); + + static inline Pointer getPointer(QQmlAbstractBinding *p); + +protected: + virtual ~QQmlAbstractBinding(); + void clear(); + + // Called by QQmlPropertyPrivate to "move" a binding to a different property. + // This is only used for alias properties, and only used by QQmlBinding not + // V8 or V4 bindings. The default implementation qFatal()'s to ensure that the + // method is never called for V4 or V8 bindings. + virtual void retargetBinding(QObject *, int); +private: + Pointer weakPointer(); + + friend class QQmlData; + friend class QQmlComponentPrivate; + friend class QQmlValueTypeProxyBinding; + friend class QQmlPropertyPrivate; + friend class QQmlVME; + friend class QtSharedPointer::ExternalRefCount; + + typedef QSharedPointer SharedPointer; + // To save memory, we also store the rarely used weakPointer() instance in here + QPointerValuePair m_mePtr; + + QQmlAbstractBinding **m_prevBinding; + QQmlAbstractBinding *m_nextBinding; +}; + +QQmlAbstractBinding::Pointer +QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p) +{ + return p ? p->weakPointer() : Pointer(); +} + +QT_END_NAMESPACE + +#endif // QQMLABSTRACTBINDING_P_H diff --git a/src/qml/qml/qqmlabstractexpression.cpp b/src/qml/qml/qqmlabstractexpression.cpp new file mode 100644 index 0000000000..8319f7a619 --- /dev/null +++ b/src/qml/qml/qqmlabstractexpression.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlabstractexpression_p.h" + +QT_BEGIN_NAMESPACE + +QQmlAbstractExpression::QQmlAbstractExpression() +: m_prevExpression(0), m_nextExpression(0) +{ +} + +QQmlAbstractExpression::~QQmlAbstractExpression() +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + } + + if (m_context.isT2()) + m_context.asT2()->_s = 0; +} + +QQmlContextData *QQmlAbstractExpression::context() const +{ + if (m_context.isT1()) return m_context.asT1(); + else return m_context.asT2()->_c; +} + +void QQmlAbstractExpression::setContext(QQmlContextData *context) +{ + if (m_prevExpression) { + *m_prevExpression = m_nextExpression; + if (m_nextExpression) + m_nextExpression->m_prevExpression = m_prevExpression; + m_prevExpression = 0; + m_nextExpression = 0; + } + + if (m_context.isT1()) m_context = context; + else m_context.asT2()->_c = context; + + if (context) { + m_nextExpression = context->expressions; + if (m_nextExpression) + m_nextExpression->m_prevExpression = &m_nextExpression; + m_prevExpression = &context->expressions; + context->expressions = this; + } +} + +void QQmlAbstractExpression::refresh() +{ +} + +bool QQmlAbstractExpression::isValid() const +{ + return context() != 0; +} + +QT_END_NAMESPACE + diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h new file mode 100644 index 0000000000..fe2ee1762b --- /dev/null +++ b/src/qml/qml/qqmlabstractexpression_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLABSTRACTEXPRESSION_P_H +#define QQMLABSTRACTEXPRESSION_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 QQmlAbstractExpression +{ +public: + QQmlAbstractExpression(); + virtual ~QQmlAbstractExpression(); + + bool isValid() const; + + QQmlContextData *context() const; + void setContext(QQmlContextData *); + + virtual void refresh(); + + class DeleteWatcher { + public: + inline DeleteWatcher(QQmlAbstractExpression *); + inline ~DeleteWatcher(); + inline bool wasDeleted() const; + private: + friend class QQmlAbstractExpression; + QQmlContextData *_c; + QQmlAbstractExpression **_w; + QQmlAbstractExpression *_s; + }; + +private: + friend class QQmlContext; + friend class QQmlContextData; + friend class QQmlContextPrivate; + + QBiPointer m_context; + QQmlAbstractExpression **m_prevExpression; + QQmlAbstractExpression *m_nextExpression; +}; + +QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e) +: _c(0), _w(0), _s(e) +{ + if (e->m_context.isT1()) { + _w = &_s; + _c = e->m_context.asT1(); + e->m_context = this; + } else { + // Another watcher is already registered + _w = &e->m_context.asT2()->_s; + } +} + +QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher() +{ + Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2())); + if (*_w && _s->m_context.asT2() == this) + _s->m_context = _c; +} + +bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const +{ + return *_w == 0; +} + +QT_END_NAMESPACE + +#endif // QQMLABSTRACTEXPRESSION_P_H diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index bb6eb3b723..23f5abf5fd 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -55,149 +55,6 @@ QT_BEGIN_NAMESPACE -QQmlAbstractBinding::QQmlAbstractBinding() -: m_prevBinding(0), m_nextBinding(0) -{ -} - -QQmlAbstractBinding::~QQmlAbstractBinding() -{ - Q_ASSERT(m_prevBinding == 0); - Q_ASSERT(*m_mePtr == 0); -} - -/*! -Destroy the binding. Use this instead of calling delete. - -Bindings are free to implement their own memory management, so the delete operator is not -necessarily safe. The default implementation clears the binding, removes it from the object -and calls delete. -*/ -void QQmlAbstractBinding::destroy() -{ - removeFromObject(); - clear(); - - delete this; -} - -/*! -Add this binding to \a object. - -This transfers ownership of the binding to the object, marks the object's property as -being bound. - -However, it does not enable the binding itself or call update() on it. -*/ -void QQmlAbstractBinding::addToObject() -{ - Q_ASSERT(!m_prevBinding); - - QObject *obj = object(); - Q_ASSERT(obj); - - int index = propertyIndex(); - - QQmlData *data = QQmlData::get(obj, true); - - if (index & 0xFF000000) { - // Value type - - int coreIndex = index & 0xFFFFFF; - - // Find the value type proxy (if there is one) - QQmlValueTypeProxyBinding *proxy = 0; - if (data->hasBindingBit(coreIndex)) { - QQmlAbstractBinding *b = data->bindings; - while (b && b->propertyIndex() != coreIndex) - b = b->m_nextBinding; - Q_ASSERT(b && b->bindingType() == QQmlAbstractBinding::ValueTypeProxy); - proxy = static_cast(b); - } - - if (!proxy) { - proxy = new QQmlValueTypeProxyBinding(obj, coreIndex); - - Q_ASSERT(proxy->propertyIndex() == coreIndex); - Q_ASSERT(proxy->object() == obj); - - proxy->addToObject(); - } - - m_nextBinding = proxy->m_bindings; - if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; - m_prevBinding = &proxy->m_bindings; - proxy->m_bindings = this; - - } else { - m_nextBinding = data->bindings; - if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; - m_prevBinding = &data->bindings; - data->bindings = this; - - data->setBindingBit(obj, index); - } -} - -/*! -Remove the binding from the object. -*/ -void QQmlAbstractBinding::removeFromObject() -{ - if (m_prevBinding) { - int index = propertyIndex(); - - *m_prevBinding = m_nextBinding; - if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; - m_prevBinding = 0; - m_nextBinding = 0; - - if (index & 0xFF000000) { - // Value type - we don't remove the proxy from the object. It will sit their happily - // doing nothing until it is removed by a write, a binding change or it is reused - // to hold more sub-bindings. - } else if (QObject *obj = object()) { - QQmlData *data = QQmlData::get(obj, false); - if (data) data->clearBindingBit(index); - } - } -} - -static void bindingDummyDeleter(QQmlAbstractBinding *) -{ -} - -QQmlAbstractBinding::Pointer QQmlAbstractBinding::weakPointer() -{ - if (m_mePtr.value().isNull()) - m_mePtr.value() = QSharedPointer(this, bindingDummyDeleter); - - return m_mePtr.value().toWeakRef(); -} - -void QQmlAbstractBinding::clear() -{ - if (!m_mePtr.isNull()) { - **m_mePtr = 0; - m_mePtr = 0; - } -} - -void QQmlAbstractBinding::retargetBinding(QObject *, int) -{ - qFatal("QQmlAbstractBinding::retargetBinding() called on illegal binding."); -} - -QString QQmlAbstractBinding::expression() const -{ - return QLatin1String(""); -} - -void QQmlAbstractBinding::setEnabled(bool enabled, QQmlPropertyPrivate::WriteFlags flags) -{ - if (enabled) update(flags); -} - QQmlBinding::Identifier QQmlBinding::Invalid = -1; void QQmlBindingPrivate::refresh() @@ -457,96 +314,4 @@ void QQmlBinding::retargetBinding(QObject *t, int i) d->targetProperty = i; } -QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index) -: m_object(o), m_index(index), m_bindings(0) -{ -} - -QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding() -{ - while (m_bindings) { - QQmlAbstractBinding *binding = m_bindings; - binding->setEnabled(false, 0); - binding->destroy(); - } -} - -void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) -{ - if (e) { - QQmlAbstractBinding *bindings = m_bindings; - recursiveEnable(bindings, flags); - } else { - QQmlAbstractBinding *bindings = m_bindings; - recursiveDisable(bindings); - } -} - -void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags) -{ - if (!b) - return; - - recursiveEnable(b->m_nextBinding, flags); - - if (b) - b->setEnabled(true, flags); -} - -void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b) -{ - if (!b) - return; - - recursiveDisable(b->m_nextBinding); - - if (b) - b->setEnabled(false, 0); -} - -void QQmlValueTypeProxyBinding::update(QQmlPropertyPrivate::WriteFlags) -{ -} - -QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex) -{ - QQmlAbstractBinding *binding = m_bindings; - - while (binding && binding->propertyIndex() != propertyIndex) - binding = binding->m_nextBinding; - - return binding; -} - -/*! -Removes a collection of bindings, corresponding to the set bits in \a mask. -*/ -void QQmlValueTypeProxyBinding::removeBindings(quint32 mask) -{ - QQmlAbstractBinding *binding = m_bindings; - while (binding) { - if (mask & (1 << (binding->propertyIndex() >> 24))) { - QQmlAbstractBinding *remove = binding; - binding = remove->m_nextBinding; - *remove->m_prevBinding = remove->m_nextBinding; - if (remove->m_nextBinding) remove->m_nextBinding->m_prevBinding = remove->m_prevBinding; - remove->m_prevBinding = 0; - remove->m_nextBinding = 0; - remove->destroy(); - } else { - binding = binding->m_nextBinding; - } - } -} - -int QQmlValueTypeProxyBinding::propertyIndex() const -{ - return m_index; -} - -QObject *QQmlValueTypeProxyBinding::object() const -{ - return m_object; -} - QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 33823d7e7e..785c96fd22 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -63,102 +63,13 @@ #include #include +#include QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlAbstractBinding -{ -public: - typedef QWeakPointer Pointer; - - QQmlAbstractBinding(); - - virtual void destroy(); - - virtual QString expression() const; - - enum Type { PropertyBinding, ValueTypeProxy }; - virtual Type bindingType() const { return PropertyBinding; } - - // Should return the encoded property index for the binding. Should return this value - // even if the binding is not enabled or added to an object. - // Encoding is: coreIndex | (valueTypeIndex << 24) - virtual int propertyIndex() const = 0; - // Should return the object for the binding. Should return this object even if the - // binding is not enabled or added to the object. - virtual QObject *object() const = 0; - - void setEnabled(bool e) { setEnabled(e, QQmlPropertyPrivate::DontRemoveBinding); } - virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags) = 0; - - void update() { update(QQmlPropertyPrivate::DontRemoveBinding); } - virtual void update(QQmlPropertyPrivate::WriteFlags) = 0; - - void addToObject(); - void removeFromObject(); - - static inline Pointer getPointer(QQmlAbstractBinding *p); - -protected: - virtual ~QQmlAbstractBinding(); - void clear(); - - // Called by QQmlPropertyPrivate to "move" a binding to a different property. - // This is only used for alias properties, and only used by QQmlBinding not - // V8 or V4 bindings. The default implementation qFatal()'s to ensure that the - // method is never called for V4 or V8 bindings. - virtual void retargetBinding(QObject *, int); -private: - Pointer weakPointer(); - - friend class QQmlData; - friend class QQmlComponentPrivate; - friend class QQmlValueTypeProxyBinding; - friend class QQmlPropertyPrivate; - friend class QQmlVME; - friend class QtSharedPointer::ExternalRefCount; - - typedef QSharedPointer SharedPointer; - // To save memory, we also store the rarely used weakPointer() instance in here - QPointerValuePair m_mePtr; - - QQmlAbstractBinding **m_prevBinding; - QQmlAbstractBinding *m_nextBinding; -}; - -class QQmlValueTypeProxyBinding : public QQmlAbstractBinding -{ -public: - QQmlValueTypeProxyBinding(QObject *o, int coreIndex); - - virtual Type bindingType() const { return ValueTypeProxy; } - - virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags); - virtual void update(QQmlPropertyPrivate::WriteFlags); - virtual int propertyIndex() const; - virtual QObject *object() const; - - QQmlAbstractBinding *binding(int propertyIndex); - - void removeBindings(quint32 mask); - -protected: - ~QQmlValueTypeProxyBinding(); - -private: - void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - void recursiveDisable(QQmlAbstractBinding *); - - friend class QQmlAbstractBinding; - QObject *m_object; - int m_index; - QQmlAbstractBinding *m_bindings; -}; - class QQmlContext; class QQmlBindingPrivate; -class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlExpression, - public QQmlAbstractBinding +class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlExpression, public QQmlAbstractBinding { Q_OBJECT public: @@ -206,12 +117,6 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlBinding::EvaluateFlags) -QQmlAbstractBinding::Pointer -QQmlAbstractBinding::getPointer(QQmlAbstractBinding *p) -{ - return p ? p->weakPointer() : Pointer(); -} - QT_END_NAMESPACE Q_DECLARE_METATYPE(QQmlBinding*) diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index ecdbf21d4b..cefde1decb 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -52,32 +52,6 @@ QT_BEGIN_NAMESPACE -bool QQmlDelayedError::addError(QQmlEnginePrivate *e) -{ - if (!e) return false; - - if (e->inProgressCreations == 0) return false; // Not in construction - - if (prevError) return true; // Already in error chain - - prevError = &e->erroredBindings; - nextError = e->erroredBindings; - e->erroredBindings = this; - if (nextError) nextError->prevError = &nextError; - - return true; -} - -QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) -: m_vtable(v) -{ -} - -QQmlJavaScriptExpression::~QQmlJavaScriptExpression() -{ - clearGuards(); -} - static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = { QQmlExpressionPrivate::expressionIdentifier, QQmlExpressionPrivate::expressionChanged @@ -514,192 +488,6 @@ void QQmlExpressionPrivate::exceptionToError(v8::Handle message, error.setDescription(qDescription); } -void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) -{ - activeGuards.setFlagValue(v); - if (!v) clearGuards(); -} - -void QQmlJavaScriptExpression::resetNotifyOnValueChanged() -{ - clearGuards(); -} - -v8::Local -QQmlJavaScriptExpression::evaluate(QQmlContextData *context, - v8::Handle function, bool *isUndefined) -{ - Q_ASSERT(context && context->engine); - - if (function.IsEmpty() || function->IsUndefined()) { - if (isUndefined) *isUndefined = true; - return v8::Local(); - } - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); - - Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); - GuardCapture capture(context->engine, this); - - QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; - ep->propertyCapture = notifyOnValueChanged()?&capture:0; - - - if (notifyOnValueChanged()) - capture.guards.copyAndClearPrepend(activeGuards); - - QQmlContextData *lastSharedContext = 0; - QObject *lastSharedScope = 0; - - bool sharedContext = useSharedContext(); - - // All code that follows must check with watcher before it accesses data members - // incase we have been deleted. - DeleteWatcher watcher(this); - - if (sharedContext) { - lastSharedContext = ep->sharedContext; - lastSharedScope = ep->sharedScope; - ep->sharedContext = context; - ep->sharedScope = scopeObject(); - } - - v8::Local result; - { - v8::TryCatch try_catch; - v8::Handle This = ep->v8engine()->global(); - if (scopeObject() && requiresThisObject()) { - v8::Handle value = ep->v8engine()->newQObject(scopeObject()); - if (value->IsObject()) This = v8::Handle::Cast(value); - } - - result = function->Call(This, 0, 0); - - if (isUndefined) - *isUndefined = try_catch.HasCaught() || result->IsUndefined(); - - if (watcher.wasDeleted()) { - } else if (try_catch.HasCaught()) { - v8::Context::Scope scope(ep->v8engine()->context()); - v8::Local message = try_catch.Message(); - if (!message.IsEmpty()) { - QQmlExpressionPrivate::exceptionToError(message, delayedError()->error); - } else { - if (hasDelayedError()) delayedError()->error = QQmlError(); - } - } else { - if (hasDelayedError()) delayedError()->error = QQmlError(); - } - } - - if (sharedContext) { - ep->sharedContext = lastSharedContext; - ep->sharedScope = lastSharedScope; - } - - if (capture.errorString) { - for (int ii = 0; ii < capture.errorString->count(); ++ii) - qWarning("%s", qPrintable(capture.errorString->at(ii))); - delete capture.errorString; - capture.errorString = 0; - } - - while (Guard *g = capture.guards.takeFirst()) - g->Delete(); - - ep->propertyCapture = lastPropertyCapture; - - return result; -} - -void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n) -{ - if (expression) { - - // Try and find a matching guard - while (!guards.isEmpty() && !guards.first()->isConnected(n)) - guards.takeFirst()->Delete(); - - Guard *g = 0; - if (!guards.isEmpty()) { - g = guards.takeFirst(); - g->cancelNotify(); - Q_ASSERT(g->isConnected(n)); - } else { - g = Guard::New(expression, engine); - g->connect(n); - } - - expression->activeGuards.prepend(g); - } -} - -void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n) -{ - if (expression) { - if (n == -1) { - if (!errorString) { - errorString = new QStringList; - QString preamble = QLatin1String("QQmlExpression: Expression ") + - expression->m_vtable->expressionIdentifier(expression) + - QLatin1String(" depends on non-NOTIFYable properties:"); - errorString->append(preamble); - } - - const QMetaObject *metaObj = o->metaObject(); - QMetaProperty metaProp = metaObj->property(c); - - QString error = QLatin1String(" ") + - QString::fromUtf8(metaObj->className()) + - QLatin1String("::") + - QString::fromUtf8(metaProp.name()); - errorString->append(error); - } else { - - // Try and find a matching guard - while (!guards.isEmpty() && !guards.first()->isConnected(o, n)) - guards.takeFirst()->Delete(); - - Guard *g = 0; - if (!guards.isEmpty()) { - g = guards.takeFirst(); - g->cancelNotify(); - Q_ASSERT(g->isConnected(o, n)); - } else { - g = Guard::New(expression, engine); - g->connect(o, n); - } - - expression->activeGuards.prepend(g); - } - } -} - -void QQmlJavaScriptExpression::clearError() -{ - if (m_vtable.hasValue()) { - m_vtable.value().error = QQmlError(); - m_vtable.value().removeError(); - } -} - -QQmlError QQmlJavaScriptExpression::error() const -{ - if (m_vtable.hasValue()) return m_vtable.constValue()->error; - else return QQmlError(); -} - -QQmlDelayedError *QQmlJavaScriptExpression::delayedError() -{ - return &m_vtable.value(); -} - -void QQmlJavaScriptExpression::clearGuards() -{ - while (Guard *g = activeGuards.takeFirst()) - g->Delete(); -} - // Must be called with a valid handle scope v8::Local QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined) { @@ -923,60 +711,6 @@ QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e) return QLatin1String("\"") + This->expression + QLatin1String("\""); } -QQmlAbstractExpression::QQmlAbstractExpression() -: m_prevExpression(0), m_nextExpression(0) -{ -} - -QQmlAbstractExpression::~QQmlAbstractExpression() -{ - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; - } - - if (m_context.isT2()) - m_context.asT2()->_s = 0; -} - -QQmlContextData *QQmlAbstractExpression::context() const -{ - if (m_context.isT1()) return m_context.asT1(); - else return m_context.asT2()->_c; -} - -void QQmlAbstractExpression::setContext(QQmlContextData *context) -{ - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; - m_prevExpression = 0; - m_nextExpression = 0; - } - - if (m_context.isT1()) m_context = context; - else m_context.asT2()->_c = context; - - if (context) { - m_nextExpression = context->expressions; - if (m_nextExpression) - m_nextExpression->m_prevExpression = &m_nextExpression; - m_prevExpression = &context->expressions; - context->expressions = this; - } -} - -void QQmlAbstractExpression::refresh() -{ -} - -bool QQmlAbstractExpression::isValid() const -{ - return context() != 0; -} - QT_END_NAMESPACE #include diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h index deca29ab60..3b335ba658 100644 --- a/src/qml/qml/qqmlexpression_p.h +++ b/src/qml/qml/qqmlexpression_p.h @@ -56,161 +56,22 @@ #include "qqmlexpression.h" #include +#include +#include #include #include #include -#include #include -#include +#include +#include QT_BEGIN_NAMESPACE -class QQmlAbstractExpression -{ -public: - QQmlAbstractExpression(); - virtual ~QQmlAbstractExpression(); - - bool isValid() const; - - QQmlContextData *context() const; - void setContext(QQmlContextData *); - - virtual void refresh(); - - class DeleteWatcher { - public: - inline DeleteWatcher(QQmlAbstractExpression *); - inline ~DeleteWatcher(); - inline bool wasDeleted() const; - private: - friend class QQmlAbstractExpression; - QQmlContextData *_c; - QQmlAbstractExpression **_w; - QQmlAbstractExpression *_s; - }; - -private: - friend class QQmlContext; - friend class QQmlContextData; - friend class QQmlContextPrivate; - - QBiPointer m_context; - QQmlAbstractExpression **m_prevExpression; - QQmlAbstractExpression *m_nextExpression; -}; - -class QQmlDelayedError -{ -public: - inline QQmlDelayedError() : nextError(0), prevError(0) {} - inline ~QQmlDelayedError() { removeError(); } - - QQmlError error; - - bool addError(QQmlEnginePrivate *); - - inline void removeError() { - if (!prevError) return; - if (nextError) nextError->prevError = prevError; - *prevError = nextError; - nextError = 0; - prevError = 0; - } - -private: - QQmlDelayedError *nextError; - QQmlDelayedError **prevError; -}; - -class QQmlJavaScriptExpression -{ -public: - // Although this looks crazy, we implement our own "vtable" here, rather than relying on - // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage - // location that is use for the vtable to also store the rarely used delayed error. - // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in - // memory for every expression. - struct VTable { - QString (*expressionIdentifier)(QQmlJavaScriptExpression *); - void (*expressionChanged)(QQmlJavaScriptExpression *); - }; - - QQmlJavaScriptExpression(VTable *vtable); - - v8::Local evaluate(QQmlContextData *, v8::Handle, - bool *isUndefined); - - inline bool requiresThisObject() const; - inline void setRequiresThisObject(bool v); - inline bool useSharedContext() const; - inline void setUseSharedContext(bool v); - inline bool notifyOnValueChanged() const; - - void setNotifyOnValueChanged(bool v); - void resetNotifyOnValueChanged(); - - inline QObject *scopeObject() const; - inline void setScopeObject(QObject *v); - - class DeleteWatcher { - public: - inline DeleteWatcher(QQmlJavaScriptExpression *); - inline ~DeleteWatcher(); - inline bool wasDeleted() const; - private: - friend class QQmlJavaScriptExpression; - QObject *_c; - QQmlJavaScriptExpression **_w; - QQmlJavaScriptExpression *_s; - }; - - inline bool hasError() const; - inline bool hasDelayedError() const; - QQmlError error() const; - void clearError(); - QQmlDelayedError *delayedError(); - -protected: - ~QQmlJavaScriptExpression(); - -private: - typedef QQmlJavaScriptExpressionGuard Guard; - friend class QQmlJavaScriptExpressionGuard; - - struct GuardCapture : public QQmlEnginePrivate::PropertyCapture { - GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e) - : engine(engine), expression(e), errorString(0) { } - - ~GuardCapture() { - Q_ASSERT(guards.isEmpty()); - Q_ASSERT(errorString == 0); - } - - virtual void captureProperty(QQmlNotifier *); - virtual void captureProperty(QObject *, int, int); - - QQmlEngine *engine; - QQmlJavaScriptExpression *expression; - QFieldList guards; - QStringList *errorString; - }; - - QPointerValuePair m_vtable; - - // We store some flag bits in the following flag pointers. - // m_scopeObject:flag1 - requiresThisObject - // activeGuards:flag1 - notifyOnValueChanged - // activeGuards:flag2 - useSharedContext - QBiPointer m_scopeObject; - QForwardFieldList activeGuards; - - void clearGuards(); -}; - class QQmlExpression; class QString; -class Q_QML_PRIVATE_EXPORT QQmlExpressionPrivate : public QObjectPrivate, public QQmlJavaScriptExpression, public QQmlAbstractExpression +class Q_QML_PRIVATE_EXPORT QQmlExpressionPrivate : public QObjectPrivate, + public QQmlJavaScriptExpression, + public QQmlAbstractExpression { Q_DECLARE_PUBLIC(QQmlExpression) public: @@ -267,103 +128,6 @@ public: QQmlRefCount *dataRef; }; -QQmlAbstractExpression::DeleteWatcher::DeleteWatcher(QQmlAbstractExpression *e) -: _c(0), _w(0), _s(e) -{ - if (e->m_context.isT1()) { - _w = &_s; - _c = e->m_context.asT1(); - e->m_context = this; - } else { - // Another watcher is already registered - _w = &e->m_context.asT2()->_s; - } -} - -QQmlAbstractExpression::DeleteWatcher::~DeleteWatcher() -{ - Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_context.isT2())); - if (*_w && _s->m_context.asT2() == this) - _s->m_context = _c; -} - -bool QQmlAbstractExpression::DeleteWatcher::wasDeleted() const -{ - return *_w == 0; -} - -QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e) -: _c(0), _w(0), _s(e) -{ - if (e->m_scopeObject.isT1()) { - _w = &_s; - _c = e->m_scopeObject.asT1(); - e->m_scopeObject = this; - } else { - // Another watcher is already registered - _w = &e->m_scopeObject.asT2()->_s; - } -} - -QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher() -{ - Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2())); - if (*_w && _s->m_scopeObject.asT2() == this) - _s->m_scopeObject = _c; -} - -bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const -{ - return *_w == 0; -} - -bool QQmlJavaScriptExpression::requiresThisObject() const -{ - return m_scopeObject.flag(); -} - -void QQmlJavaScriptExpression::setRequiresThisObject(bool v) -{ - m_scopeObject.setFlagValue(v); -} - -bool QQmlJavaScriptExpression::useSharedContext() const -{ - return activeGuards.flag2(); -} - -void QQmlJavaScriptExpression::setUseSharedContext(bool v) -{ - activeGuards.setFlag2Value(v); -} - -bool QQmlJavaScriptExpression::notifyOnValueChanged() const -{ - return activeGuards.flag(); -} - -QObject *QQmlJavaScriptExpression::scopeObject() const -{ - if (m_scopeObject.isT1()) return m_scopeObject.asT1(); - else return m_scopeObject.asT2()->_c; -} - -void QQmlJavaScriptExpression::setScopeObject(QObject *v) -{ - if (m_scopeObject.isT1()) m_scopeObject = v; - else m_scopeObject.asT2()->_c = v; -} - -bool QQmlJavaScriptExpression::hasError() const -{ - return m_vtable.hasValue() && m_vtable.constValue()->error.isValid(); -} - -bool QQmlJavaScriptExpression::hasDelayedError() const -{ - return m_vtable.hasValue(); -} - QQmlExpressionPrivate *QQmlExpressionPrivate::get(QQmlExpression *expr) { return static_cast(QObjectPrivate::get(expr)); @@ -374,32 +138,6 @@ QQmlExpression *QQmlExpressionPrivate::get(QQmlExpressionPrivate *expr) return expr->q_func(); } -QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e) -: expression(e), next(0) -{ - callback = &endpointCallback; -} - -void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e) -{ - QQmlJavaScriptExpression *expression = - static_cast(e)->expression; - - expression->m_vtable->expressionChanged(expression); -} - -QQmlJavaScriptExpressionGuard * -QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e, - QQmlEngine *engine) -{ - Q_ASSERT(e); - return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e); -} - -void QQmlJavaScriptExpressionGuard::Delete() -{ - QRecyclePool::Delete(this); -} QT_END_NAMESPACE diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp new file mode 100644 index 0000000000..4186b5b53d --- /dev/null +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmljavascriptexpression_p.h" + +#include + +QT_BEGIN_NAMESPACE + +bool QQmlDelayedError::addError(QQmlEnginePrivate *e) +{ + if (!e) return false; + + if (e->inProgressCreations == 0) return false; // Not in construction + + if (prevError) return true; // Already in error chain + + prevError = &e->erroredBindings; + nextError = e->erroredBindings; + e->erroredBindings = this; + if (nextError) nextError->prevError = &nextError; + + return true; +} + +QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) +: m_vtable(v) +{ +} + +QQmlJavaScriptExpression::~QQmlJavaScriptExpression() +{ + clearGuards(); +} + +void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) +{ + activeGuards.setFlagValue(v); + if (!v) clearGuards(); +} + +void QQmlJavaScriptExpression::resetNotifyOnValueChanged() +{ + clearGuards(); +} + +v8::Local +QQmlJavaScriptExpression::evaluate(QQmlContextData *context, + v8::Handle function, bool *isUndefined) +{ + Q_ASSERT(context && context->engine); + + if (function.IsEmpty() || function->IsUndefined()) { + if (isUndefined) *isUndefined = true; + return v8::Local(); + } + + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); + + Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); + GuardCapture capture(context->engine, this); + + QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; + ep->propertyCapture = notifyOnValueChanged()?&capture:0; + + + if (notifyOnValueChanged()) + capture.guards.copyAndClearPrepend(activeGuards); + + QQmlContextData *lastSharedContext = 0; + QObject *lastSharedScope = 0; + + bool sharedContext = useSharedContext(); + + // All code that follows must check with watcher before it accesses data members + // incase we have been deleted. + DeleteWatcher watcher(this); + + if (sharedContext) { + lastSharedContext = ep->sharedContext; + lastSharedScope = ep->sharedScope; + ep->sharedContext = context; + ep->sharedScope = scopeObject(); + } + + v8::Local result; + { + v8::TryCatch try_catch; + v8::Handle This = ep->v8engine()->global(); + if (scopeObject() && requiresThisObject()) { + v8::Handle value = ep->v8engine()->newQObject(scopeObject()); + if (value->IsObject()) This = v8::Handle::Cast(value); + } + + result = function->Call(This, 0, 0); + + if (isUndefined) + *isUndefined = try_catch.HasCaught() || result->IsUndefined(); + + if (watcher.wasDeleted()) { + } else if (try_catch.HasCaught()) { + v8::Context::Scope scope(ep->v8engine()->context()); + v8::Local message = try_catch.Message(); + if (!message.IsEmpty()) { + QQmlExpressionPrivate::exceptionToError(message, delayedError()->error); + } else { + if (hasDelayedError()) delayedError()->error = QQmlError(); + } + } else { + if (hasDelayedError()) delayedError()->error = QQmlError(); + } + } + + if (sharedContext) { + ep->sharedContext = lastSharedContext; + ep->sharedScope = lastSharedScope; + } + + if (capture.errorString) { + for (int ii = 0; ii < capture.errorString->count(); ++ii) + qWarning("%s", qPrintable(capture.errorString->at(ii))); + delete capture.errorString; + capture.errorString = 0; + } + + while (Guard *g = capture.guards.takeFirst()) + g->Delete(); + + ep->propertyCapture = lastPropertyCapture; + + return result; +} + +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n) +{ + if (expression) { + + // Try and find a matching guard + while (!guards.isEmpty() && !guards.first()->isConnected(n)) + guards.takeFirst()->Delete(); + + Guard *g = 0; + if (!guards.isEmpty()) { + g = guards.takeFirst(); + g->cancelNotify(); + Q_ASSERT(g->isConnected(n)); + } else { + g = Guard::New(expression, engine); + g->connect(n); + } + + expression->activeGuards.prepend(g); + } +} + +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n) +{ + if (expression) { + if (n == -1) { + if (!errorString) { + errorString = new QStringList; + QString preamble = QLatin1String("QQmlExpression: Expression ") + + expression->m_vtable->expressionIdentifier(expression) + + QLatin1String(" depends on non-NOTIFYable properties:"); + errorString->append(preamble); + } + + const QMetaObject *metaObj = o->metaObject(); + QMetaProperty metaProp = metaObj->property(c); + + QString error = QLatin1String(" ") + + QString::fromUtf8(metaObj->className()) + + QLatin1String("::") + + QString::fromUtf8(metaProp.name()); + errorString->append(error); + } else { + + // Try and find a matching guard + while (!guards.isEmpty() && !guards.first()->isConnected(o, n)) + guards.takeFirst()->Delete(); + + Guard *g = 0; + if (!guards.isEmpty()) { + g = guards.takeFirst(); + g->cancelNotify(); + Q_ASSERT(g->isConnected(o, n)); + } else { + g = Guard::New(expression, engine); + g->connect(o, n); + } + + expression->activeGuards.prepend(g); + } + } +} + +void QQmlJavaScriptExpression::clearError() +{ + if (m_vtable.hasValue()) { + m_vtable.value().error = QQmlError(); + m_vtable.value().removeError(); + } +} + +QQmlError QQmlJavaScriptExpression::error() const +{ + if (m_vtable.hasValue()) return m_vtable.constValue()->error; + else return QQmlError(); +} + +QQmlDelayedError *QQmlJavaScriptExpression::delayedError() +{ + return &m_vtable.value(); +} + +void QQmlJavaScriptExpression::clearGuards() +{ + while (Guard *g = activeGuards.takeFirst()) + g->Delete(); +} + +QT_END_NAMESPACE diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h new file mode 100644 index 0000000000..1da1e12ebd --- /dev/null +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLJAVASCRIPTEXPRESSION_P_H +#define QQMLJAVASCRIPTEXPRESSION_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 +#include +#include + +QT_BEGIN_NAMESPACE + +class QQmlDelayedError +{ +public: + inline QQmlDelayedError() : nextError(0), prevError(0) {} + inline ~QQmlDelayedError() { removeError(); } + + QQmlError error; + + bool addError(QQmlEnginePrivate *); + + inline void removeError() { + if (!prevError) return; + if (nextError) nextError->prevError = prevError; + *prevError = nextError; + nextError = 0; + prevError = 0; + } + +private: + QQmlDelayedError *nextError; + QQmlDelayedError **prevError; +}; + +class QQmlJavaScriptExpression +{ +public: + // Although this looks crazy, we implement our own "vtable" here, rather than relying on + // C++ virtuals, to save memory. By doing it ourselves, we can overload the storage + // location that is use for the vtable to also store the rarely used delayed error. + // If we use C++ virtuals, we can't do this and it consts us an extra sizeof(void *) in + // memory for every expression. + struct VTable { + QString (*expressionIdentifier)(QQmlJavaScriptExpression *); + void (*expressionChanged)(QQmlJavaScriptExpression *); + }; + + QQmlJavaScriptExpression(VTable *vtable); + + v8::Local evaluate(QQmlContextData *, v8::Handle, + bool *isUndefined); + + inline bool requiresThisObject() const; + inline void setRequiresThisObject(bool v); + inline bool useSharedContext() const; + inline void setUseSharedContext(bool v); + inline bool notifyOnValueChanged() const; + + void setNotifyOnValueChanged(bool v); + void resetNotifyOnValueChanged(); + + inline QObject *scopeObject() const; + inline void setScopeObject(QObject *v); + + class DeleteWatcher { + public: + inline DeleteWatcher(QQmlJavaScriptExpression *); + inline ~DeleteWatcher(); + inline bool wasDeleted() const; + private: + friend class QQmlJavaScriptExpression; + QObject *_c; + QQmlJavaScriptExpression **_w; + QQmlJavaScriptExpression *_s; + }; + + inline bool hasError() const; + inline bool hasDelayedError() const; + QQmlError error() const; + void clearError(); + QQmlDelayedError *delayedError(); + +protected: + ~QQmlJavaScriptExpression(); + +private: + typedef QQmlJavaScriptExpressionGuard Guard; + friend class QQmlJavaScriptExpressionGuard; + + struct GuardCapture : public QQmlEnginePrivate::PropertyCapture { + GuardCapture(QQmlEngine *engine, QQmlJavaScriptExpression *e) + : engine(engine), expression(e), errorString(0) { } + + ~GuardCapture() { + Q_ASSERT(guards.isEmpty()); + Q_ASSERT(errorString == 0); + } + + virtual void captureProperty(QQmlNotifier *); + virtual void captureProperty(QObject *, int, int); + + QQmlEngine *engine; + QQmlJavaScriptExpression *expression; + QFieldList guards; + QStringList *errorString; + }; + + QPointerValuePair m_vtable; + + // We store some flag bits in the following flag pointers. + // m_scopeObject:flag1 - requiresThisObject + // activeGuards:flag1 - notifyOnValueChanged + // activeGuards:flag2 - useSharedContext + QBiPointer m_scopeObject; + QForwardFieldList activeGuards; + + void clearGuards(); +}; + +QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e) +: _c(0), _w(0), _s(e) +{ + if (e->m_scopeObject.isT1()) { + _w = &_s; + _c = e->m_scopeObject.asT1(); + e->m_scopeObject = this; + } else { + // Another watcher is already registered + _w = &e->m_scopeObject.asT2()->_s; + } +} + +QQmlJavaScriptExpression::DeleteWatcher::~DeleteWatcher() +{ + Q_ASSERT(*_w == 0 || (*_w == _s && _s->m_scopeObject.isT2())); + if (*_w && _s->m_scopeObject.asT2() == this) + _s->m_scopeObject = _c; +} + +bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const +{ + return *_w == 0; +} + +bool QQmlJavaScriptExpression::requiresThisObject() const +{ + return m_scopeObject.flag(); +} + +void QQmlJavaScriptExpression::setRequiresThisObject(bool v) +{ + m_scopeObject.setFlagValue(v); +} + +bool QQmlJavaScriptExpression::useSharedContext() const +{ + return activeGuards.flag2(); +} + +void QQmlJavaScriptExpression::setUseSharedContext(bool v) +{ + activeGuards.setFlag2Value(v); +} + +bool QQmlJavaScriptExpression::notifyOnValueChanged() const +{ + return activeGuards.flag(); +} + +QObject *QQmlJavaScriptExpression::scopeObject() const +{ + if (m_scopeObject.isT1()) return m_scopeObject.asT1(); + else return m_scopeObject.asT2()->_c; +} + +void QQmlJavaScriptExpression::setScopeObject(QObject *v) +{ + if (m_scopeObject.isT1()) m_scopeObject = v; + else m_scopeObject.asT2()->_c = v; +} + +bool QQmlJavaScriptExpression::hasError() const +{ + return m_vtable.hasValue() && m_vtable.constValue()->error.isValid(); +} + +bool QQmlJavaScriptExpression::hasDelayedError() const +{ + return m_vtable.hasValue(); +} + +QQmlJavaScriptExpressionGuard::QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *e) +: expression(e), next(0) +{ + callback = &endpointCallback; +} + +void QQmlJavaScriptExpressionGuard::endpointCallback(QQmlNotifierEndpoint *e) +{ + QQmlJavaScriptExpression *expression = + static_cast(e)->expression; + + expression->m_vtable->expressionChanged(expression); +} + +QQmlJavaScriptExpressionGuard * +QQmlJavaScriptExpressionGuard::New(QQmlJavaScriptExpression *e, + QQmlEngine *engine) +{ + Q_ASSERT(e); + return QQmlEnginePrivate::get(engine)->jsExpressionGuardPool.New(e); +} + +void QQmlJavaScriptExpressionGuard::Delete() +{ + QRecyclePool::Delete(this); +} + + +QT_END_NAMESPACE + +#endif // QQMLJAVASCRIPTEXPRESSION_P_H diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 6321592e9a..8d5d83ee1b 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -55,6 +55,7 @@ #include "qqmlcompiler_p.h" #include "qqmlvmemetaobject_p.h" #include "qqmlexpression_p.h" +#include "qqmlvaluetypeproxybinding_p.h" #include #include diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp new file mode 100644 index 0000000000..2cc15a50f5 --- /dev/null +++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlvaluetypeproxybinding_p.h" + +QT_BEGIN_NAMESPACE + +QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index) +: m_object(o), m_index(index), m_bindings(0) +{ +} + +QQmlValueTypeProxyBinding::~QQmlValueTypeProxyBinding() +{ + while (m_bindings) { + QQmlAbstractBinding *binding = m_bindings; + binding->setEnabled(false, 0); + binding->destroy(); + } +} + +void QQmlValueTypeProxyBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) +{ + if (e) { + QQmlAbstractBinding *bindings = m_bindings; + recursiveEnable(bindings, flags); + } else { + QQmlAbstractBinding *bindings = m_bindings; + recursiveDisable(bindings); + } +} + +void QQmlValueTypeProxyBinding::recursiveEnable(QQmlAbstractBinding *b, QQmlPropertyPrivate::WriteFlags flags) +{ + if (!b) + return; + + recursiveEnable(b->m_nextBinding, flags); + + if (b) + b->setEnabled(true, flags); +} + +void QQmlValueTypeProxyBinding::recursiveDisable(QQmlAbstractBinding *b) +{ + if (!b) + return; + + recursiveDisable(b->m_nextBinding); + + if (b) + b->setEnabled(false, 0); +} + +void QQmlValueTypeProxyBinding::update(QQmlPropertyPrivate::WriteFlags) +{ +} + +QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex) +{ + QQmlAbstractBinding *binding = m_bindings; + + while (binding && binding->propertyIndex() != propertyIndex) + binding = binding->m_nextBinding; + + return binding; +} + +/*! +Removes a collection of bindings, corresponding to the set bits in \a mask. +*/ +void QQmlValueTypeProxyBinding::removeBindings(quint32 mask) +{ + QQmlAbstractBinding *binding = m_bindings; + while (binding) { + if (mask & (1 << (binding->propertyIndex() >> 24))) { + QQmlAbstractBinding *remove = binding; + binding = remove->m_nextBinding; + *remove->m_prevBinding = remove->m_nextBinding; + if (remove->m_nextBinding) remove->m_nextBinding->m_prevBinding = remove->m_prevBinding; + remove->m_prevBinding = 0; + remove->m_nextBinding = 0; + remove->destroy(); + } else { + binding = binding->m_nextBinding; + } + } +} + +int QQmlValueTypeProxyBinding::propertyIndex() const +{ + return m_index; +} + +QObject *QQmlValueTypeProxyBinding::object() const +{ + return m_object; +} + +QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h new file mode 100644 index 0000000000..0135d575df --- /dev/null +++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLVALUETYPEPROXYBINDING_P_H +#define QQMLVALUETYPEPROXYBINDING_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 QQmlValueTypeProxyBinding : public QQmlAbstractBinding +{ +public: + QQmlValueTypeProxyBinding(QObject *o, int coreIndex); + + virtual Type bindingType() const { return ValueTypeProxy; } + + virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags); + virtual void update(QQmlPropertyPrivate::WriteFlags); + virtual int propertyIndex() const; + virtual QObject *object() const; + + QQmlAbstractBinding *binding(int propertyIndex); + + void removeBindings(quint32 mask); + +protected: + ~QQmlValueTypeProxyBinding(); + +private: + void recursiveEnable(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); + void recursiveDisable(QQmlAbstractBinding *); + + friend class QQmlAbstractBinding; + QObject *m_object; + int m_index; + QQmlAbstractBinding *m_bindings; +}; + +QT_END_NAMESPACE + +#endif // QQMLVALUETYPEPROXYBINDING_P_H diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 2b66e00bad..99979ab617 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -66,6 +66,7 @@ #include "qqmlscriptstring.h" #include "qqmlscriptstring_p.h" #include "qqmlpropertyvalueinterceptor_p.h" +#include "qqmlvaluetypeproxybinding_p.h" #include #include -- cgit v1.2.3 From d3260e2fe2564e39a8e5469a1b77b60b6f97e5a8 Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 6 Mar 2012 12:03:36 +1000 Subject: Refactor localstorage example Change-Id: I0c742c35ba8d5a2812dc1665905e45f5ffb745b5 Reviewed-by: Alan Alpert --- examples/localstorage/localstorage.pro | 10 +++- examples/localstorage/localstorage.qml | 66 +++++++++++++++++++++++++++ examples/localstorage/localstorage.qmlproject | 16 +++++++ examples/localstorage/main.cpp | 41 +++++++++++++++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 examples/localstorage/localstorage.qml create mode 100644 examples/localstorage/localstorage.qmlproject create mode 100644 examples/localstorage/main.cpp diff --git a/examples/localstorage/localstorage.pro b/examples/localstorage/localstorage.pro index 967108504e..99f498d5df 100644 --- a/examples/localstorage/localstorage.pro +++ b/examples/localstorage/localstorage.pro @@ -1 +1,9 @@ -TEMPLATE = subdirs +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/localstorage +qml.files = localstorage.qml hello.qml +qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/localstorage +INSTALLS += target qml \ No newline at end of file diff --git a/examples/localstorage/localstorage.qml b/examples/localstorage/localstorage.qml new file mode 100644 index 0000000000..f967518de8 --- /dev/null +++ b/examples/localstorage/localstorage.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "../shared" as Examples + +/*! + \title QtQuick Examples - Local Storage + \example qtquick/localstorage + \brief This is a collection of QML local storage examples + \image qml-localstorage-example.png + + This is a collection of small QML examples relating to local storage functionality. + + Hello World demos creating a simple SQL table and how to do inserting/selecting operations. + +*/ + +Item { + height: 480 + width: 320 + Examples.LauncherList { + id: ll + anchors.fill: parent + Component.onCompleted: { + addExample("Hello World", "Simple SQL operations with local storage API", Qt.resolvedUrl("hello.qml")); + } + } +} \ No newline at end of file diff --git a/examples/localstorage/localstorage.qmlproject b/examples/localstorage/localstorage.qmlproject new file mode 100644 index 0000000000..6835d23503 --- /dev/null +++ b/examples/localstorage/localstorage.qmlproject @@ -0,0 +1,16 @@ +import QmlProject 1.0 + +Project { + mainFile: "localstorage.qml" + /* Include .qml, .js, and image files from current directory and subdirectories */ + + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } +} \ No newline at end of file diff --git a/examples/localstorage/main.cpp b/examples/localstorage/main.cpp new file mode 100644 index 0000000000..484fcdbefc --- /dev/null +++ b/examples/localstorage/main.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(localstorage) \ No newline at end of file -- cgit v1.2.3 From 656d1a147db433518236ad886074d27ed20e70ec Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 6 Mar 2012 12:13:44 +1000 Subject: Refactor XMLHttpRequest example. Change-Id: I4fd4fa4fb190814e1e32ce847d05ab0015ad4ca0 Reviewed-by: Alan Alpert --- examples/qml/xmlhttprequest/get.qml | 95 ++++++++++++++++++++++ examples/qml/xmlhttprequest/main.cpp | 41 ++++++++++ .../qml/xmlhttprequest/xmlhttprequest-example.qml | 95 ---------------------- examples/qml/xmlhttprequest/xmlhttprequest.pro | 9 ++ examples/qml/xmlhttprequest/xmlhttprequest.qml | 66 +++++++++++++++ .../qml/xmlhttprequest/xmlhttprequest.qmlproject | 16 ++++ 6 files changed, 227 insertions(+), 95 deletions(-) create mode 100644 examples/qml/xmlhttprequest/get.qml create mode 100644 examples/qml/xmlhttprequest/main.cpp delete mode 100644 examples/qml/xmlhttprequest/xmlhttprequest-example.qml create mode 100644 examples/qml/xmlhttprequest/xmlhttprequest.pro create mode 100644 examples/qml/xmlhttprequest/xmlhttprequest.qml create mode 100644 examples/qml/xmlhttprequest/xmlhttprequest.qmlproject diff --git a/examples/qml/xmlhttprequest/get.qml b/examples/qml/xmlhttprequest/get.qml new file mode 100644 index 0000000000..28ba078160 --- /dev/null +++ b/examples/qml/xmlhttprequest/get.qml @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 350; height: 400 + + function showRequestInfo(text) { + log.text = log.text + "\n" + text + console.log(text) + } + + Text { id: log; anchors.fill: parent; anchors.margins: 10 } + + Rectangle { + id: button + anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; anchors.margins: 10 + width: buttonText.width + 10; height: buttonText.height + 10 + border.width: mouseArea.pressed ? 2 : 1 + radius : 5; smooth: true + + Text { id: buttonText; anchors.centerIn: parent; text: "Request data.xml" } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: { + log.text = "" + console.log("\n") + + var doc = new XMLHttpRequest(); + doc.onreadystatechange = function() { + if (doc.readyState == XMLHttpRequest.HEADERS_RECEIVED) { + showRequestInfo("Headers -->"); + showRequestInfo(doc.getAllResponseHeaders ()); + showRequestInfo("Last modified -->"); + showRequestInfo(doc.getResponseHeader ("Last-Modified")); + + } else if (doc.readyState == XMLHttpRequest.DONE) { + var a = doc.responseXML.documentElement; + for (var ii = 0; ii < a.childNodes.length; ++ii) { + showRequestInfo(a.childNodes[ii].nodeName); + } + showRequestInfo("Headers -->"); + showRequestInfo(doc.getAllResponseHeaders ()); + showRequestInfo("Last modified -->"); + showRequestInfo(doc.getResponseHeader ("Last-Modified")); + } + } + + doc.open("GET", "data.xml"); + doc.send(); + } + } + } +} + diff --git a/examples/qml/xmlhttprequest/main.cpp b/examples/qml/xmlhttprequest/main.cpp new file mode 100644 index 0000000000..8768dd1cfd --- /dev/null +++ b/examples/qml/xmlhttprequest/main.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "../../shared/shared.h" +DECLARATIVE_EXAMPLE_MAIN(xmlhttprequest) \ No newline at end of file diff --git a/examples/qml/xmlhttprequest/xmlhttprequest-example.qml b/examples/qml/xmlhttprequest/xmlhttprequest-example.qml deleted file mode 100644 index 28ba078160..0000000000 --- a/examples/qml/xmlhttprequest/xmlhttprequest-example.qml +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - width: 350; height: 400 - - function showRequestInfo(text) { - log.text = log.text + "\n" + text - console.log(text) - } - - Text { id: log; anchors.fill: parent; anchors.margins: 10 } - - Rectangle { - id: button - anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; anchors.margins: 10 - width: buttonText.width + 10; height: buttonText.height + 10 - border.width: mouseArea.pressed ? 2 : 1 - radius : 5; smooth: true - - Text { id: buttonText; anchors.centerIn: parent; text: "Request data.xml" } - - MouseArea { - id: mouseArea - anchors.fill: parent - onClicked: { - log.text = "" - console.log("\n") - - var doc = new XMLHttpRequest(); - doc.onreadystatechange = function() { - if (doc.readyState == XMLHttpRequest.HEADERS_RECEIVED) { - showRequestInfo("Headers -->"); - showRequestInfo(doc.getAllResponseHeaders ()); - showRequestInfo("Last modified -->"); - showRequestInfo(doc.getResponseHeader ("Last-Modified")); - - } else if (doc.readyState == XMLHttpRequest.DONE) { - var a = doc.responseXML.documentElement; - for (var ii = 0; ii < a.childNodes.length; ++ii) { - showRequestInfo(a.childNodes[ii].nodeName); - } - showRequestInfo("Headers -->"); - showRequestInfo(doc.getAllResponseHeaders ()); - showRequestInfo("Last modified -->"); - showRequestInfo(doc.getResponseHeader ("Last-Modified")); - } - } - - doc.open("GET", "data.xml"); - doc.send(); - } - } - } -} - diff --git a/examples/qml/xmlhttprequest/xmlhttprequest.pro b/examples/qml/xmlhttprequest/xmlhttprequest.pro new file mode 100644 index 0000000000..468afdfc65 --- /dev/null +++ b/examples/qml/xmlhttprequest/xmlhttprequest.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +QT += quick qml +SOURCES += main.cpp + +target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/xmlhttprequest +qml.files = xmlhttprequest.qml get.qml +qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/xmlhttprequest +INSTALLS += target qml \ No newline at end of file diff --git a/examples/qml/xmlhttprequest/xmlhttprequest.qml b/examples/qml/xmlhttprequest/xmlhttprequest.qml new file mode 100644 index 0000000000..efe7d428db --- /dev/null +++ b/examples/qml/xmlhttprequest/xmlhttprequest.qml @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import "../../shared" as Examples + +/*! + \title QtQuick Examples - XMLHttpRequst + \example qtquick/xmlhttprequest + \brief This is a collection of XMLHttpRequest examples + \image qml-xmlhttprequest-example.png + + This is a collection of small QML examples relating to XML HTTP request functionality. + + Get data demos sending get XML request and showing the received header and XML body. + +*/ + +Item { + height: 480 + width: 320 + Examples.LauncherList { + id: ll + anchors.fill: parent + Component.onCompleted: { + addExample("Get data", "Send get request and show received header and body", Qt.resolvedUrl("get.qml")); + } + } +} \ No newline at end of file diff --git a/examples/qml/xmlhttprequest/xmlhttprequest.qmlproject b/examples/qml/xmlhttprequest/xmlhttprequest.qmlproject new file mode 100644 index 0000000000..088042a100 --- /dev/null +++ b/examples/qml/xmlhttprequest/xmlhttprequest.qmlproject @@ -0,0 +1,16 @@ +import QmlProject 1.0 + +Project { + mainFile: "xmlhttprequest.qml" + /* Include .qml, .js, and image files from current directory and subdirectories */ + + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } +} \ No newline at end of file -- cgit v1.2.3 From 340c479bb17c8c14013cedd7c8eece30bf206c89 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Mon, 27 Feb 2012 11:11:10 +1000 Subject: Only attempt to load QML test cases from source directory if it exists. When running installed unit tests the QML test cases are likely not in the source directory, but in the same directory as the installed test binary. If the source directory does not exist, fall back to searching for QML test cases in the current directory. Change-Id: I231b9cd49b12d88dd6cfbcc8dfb8b6c2c69d5aad Reviewed-by: Yunqiao Yin --- src/qmltest/quicktest.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 2e32a60b2d..1c69cee456 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -203,8 +203,11 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport } // Determine where to look for the test data. - if (testPath.isEmpty() && sourceDir) - testPath = QString::fromLocal8Bit(sourceDir); + if (testPath.isEmpty() && sourceDir) { + const QString s = QString::fromLocal8Bit(sourceDir); + if (QFile::exists(s)) + testPath = s; + } if (testPath.isEmpty()) { QDir current = QDir::current(); #ifdef Q_OS_WIN -- cgit v1.2.3 From fa9fcf2fb259b1b3eb09e0c853075ca328e930c5 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Mon, 12 Mar 2012 11:54:11 +1000 Subject: Fix crash when writing property after engine deletion Previously, the engine pointer stored in a QQmlProperty could be stale due to engine deletion. This commit ensures we guard that pointer. Also reverts cbb7f8b10e99fad675839d7625d3236ed67b3e01 Task-number: QTBUG-24734 Change-Id: I5349c51fbd19fa46a8710280173c1d224358b96e Reviewed-by: Michael Brasser --- src/qml/qml/qqmlproperty_p.h | 3 ++- tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index 0f97a63155..dc0235517d 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -54,6 +54,7 @@ // #include "qqmlproperty.h" +#include "qqmlengine.h" #include #include @@ -77,7 +78,7 @@ public: Q_DECLARE_FLAGS(WriteFlags, WriteFlag) QQmlContextData *context; - QQmlEngine *engine; + QQmlGuard engine; QQmlGuard object; QQmlPropertyData core; diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 13ea1abd73..ae300900c9 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -1553,8 +1553,6 @@ void tst_qqmlproperty::crashOnValueProperty() delete engine; engine = 0; - QSKIP("QTBUG-24734: test accesses deleted QML engine from QQmlProperty::propertyTypeName()"); - QCOMPARE(p.propertyTypeName(), "int"); QCOMPARE(p.read(), QVariant(10)); p.write(QVariant(20)); -- cgit v1.2.3 From d541fdcbe68ea6fab78db1009d8291c7f73cc1e5 Mon Sep 17 00:00:00 2001 From: Toby Tomkins Date: Tue, 13 Mar 2012 11:17:54 +1000 Subject: Default image scaling behaviour has changed; fix autotest. The default image scaling behaviour has changed in qtdeclarative. This change fixes the autotest to conform to fixed ratio scaling. Change-Id: I9c901825295fb04cab74c46f61696c5274ddd943 Reviewed-by: Martin Jones --- tests/auto/quick/qquickimage/tst_qquickimage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index eda56fa789..be815d8973 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -369,11 +369,11 @@ void tst_qquickimage::svg() QQuickImage *obj = qobject_cast(component.create()); QVERIFY(obj != 0); QCOMPARE(obj->width(), 300.0); - QCOMPARE(obj->height(), 300.0); + QCOMPARE(obj->height(), 273.0); obj->setSourceSize(QSize(200,200)); QCOMPARE(obj->width(), 200.0); - QCOMPARE(obj->height(), 200.0); + QCOMPARE(obj->height(), 182.0); delete obj; } -- cgit v1.2.3 From 1f76525c5f701f612b56a49715cda6597e3727b1 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 8 Mar 2012 16:50:14 +0100 Subject: QmlProfiler: updated standalone app Using a stripped-down version of the profiler data structure. Change-Id: I93a0b12462edea0ca8a1d0db42aa892aa2afc919 Reviewed-by: Kai Koehne --- tools/qmlprofiler/constants.h | 11 +- tools/qmlprofiler/profileclient.cpp | 300 ---- tools/qmlprofiler/profileclient.h | 139 -- tools/qmlprofiler/profiledata.cpp | 1902 -------------------------- tools/qmlprofiler/profiledata.h | 247 ---- tools/qmlprofiler/qmlprofiler.pro | 11 +- tools/qmlprofiler/qmlprofilerapplication.cpp | 22 +- tools/qmlprofiler/qmlprofilerapplication.h | 9 +- tools/qmlprofiler/qmlprofilerclient.cpp | 300 ++++ tools/qmlprofiler/qmlprofilerclient.h | 138 ++ tools/qmlprofiler/qmlprofilerdata.cpp | 602 ++++++++ tools/qmlprofiler/qmlprofilerdata.h | 104 ++ tools/qmlprofiler/qmlprofilereventlocation.h | 61 + 13 files changed, 1228 insertions(+), 2618 deletions(-) delete mode 100644 tools/qmlprofiler/profileclient.cpp delete mode 100644 tools/qmlprofiler/profileclient.h delete mode 100644 tools/qmlprofiler/profiledata.cpp delete mode 100644 tools/qmlprofiler/profiledata.h create mode 100644 tools/qmlprofiler/qmlprofilerclient.cpp create mode 100644 tools/qmlprofiler/qmlprofilerclient.h create mode 100644 tools/qmlprofiler/qmlprofilerdata.cpp create mode 100644 tools/qmlprofiler/qmlprofilerdata.h create mode 100644 tools/qmlprofiler/qmlprofilereventlocation.h diff --git a/tools/qmlprofiler/constants.h b/tools/qmlprofiler/constants.h index e5a1f8025d..d87bad18b1 100644 --- a/tools/qmlprofiler/constants.h +++ b/tools/qmlprofiler/constants.h @@ -54,15 +54,6 @@ const char CMD_RECORD2[] ="r"; const char CMD_QUIT[] ="quit"; const char CMD_QUIT2[] = "q"; -const char TYPE_PAINTING_STR[] = "Painting"; -const char TYPE_COMPILING_STR[] = "Compiling"; -const char TYPE_CREATING_STR[] = "Creating"; -const char TYPE_BINDING_STR[] = "Binding"; -const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; -const char PROFILER_FILE_VERSION[] = "1.02"; - -const int MIN_LEVEL = 1; - -} // Contants +} // Constants #endif // CONSTANTS_H diff --git a/tools/qmlprofiler/profileclient.cpp b/tools/qmlprofiler/profileclient.cpp deleted file mode 100644 index 85287464cf..0000000000 --- a/tools/qmlprofiler/profileclient.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "profileclient.h" - -#include -#include - -ProfileClient::ProfileClient(const QString &clientName, - QQmlDebugConnection *client) - : QQmlDebugClient(clientName, client), - m_recording(false), - m_enabled(false) -{ -} - -ProfileClient::~ProfileClient() -{ - //Disable profiling if started by client - //Profiling data will be lost!! - if (isRecording()) - setRecording(false); -} - -void ProfileClient::clearData() -{ - emit cleared(); -} - -bool ProfileClient::isEnabled() const -{ - return m_enabled; -} - -void ProfileClient::sendRecordingStatus() -{ -} - -bool ProfileClient::isRecording() const -{ - return m_recording; -} - -void ProfileClient::setRecording(bool v) -{ - if (v == m_recording) - return; - - m_recording = v; - - if (state() == Enabled) { - sendRecordingStatus(); - } - - emit recordingChanged(v); -} - -void ProfileClient::stateChanged(State status) -{ - if ((m_enabled && status != Enabled) || - (!m_enabled && status == Enabled)) - emit enabledChanged(); - - m_enabled = status == Enabled; - -} - -class QmlProfileClientPrivate -{ -public: - QmlProfileClientPrivate() - : inProgressRanges(0) - , maximumTime(0) - { - ::memset(rangeCount, 0, - QQmlProfilerService::MaximumRangeType * sizeof(int)); - } - - qint64 inProgressRanges; - QStack rangeStartTimes[QQmlProfilerService::MaximumRangeType]; - QStack rangeDatas[QQmlProfilerService::MaximumRangeType]; - QStack rangeLocations[QQmlProfilerService::MaximumRangeType]; - int rangeCount[QQmlProfilerService::MaximumRangeType]; - qint64 maximumTime; -}; - -QmlProfileClient::QmlProfileClient( - QQmlDebugConnection *client) - : ProfileClient(QLatin1String("CanvasFrameRate"), client), - d(new QmlProfileClientPrivate) -{ -} - -QmlProfileClient::~QmlProfileClient() -{ - delete d; -} - -void QmlProfileClient::clearData() -{ - ::memset(d->rangeCount, 0, - QQmlProfilerService::MaximumRangeType * sizeof(int)); - ProfileClient::clearData(); -} - -void QmlProfileClient::sendRecordingStatus() -{ - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - stream << isRecording(); - sendMessage(ba); -} - -void QmlProfileClient::messageReceived(const QByteArray &data) -{ - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - qint64 time; - int messageType; - - stream >> time >> messageType; - - if (messageType >= QQmlProfilerService::MaximumMessage) - return; - - if (messageType == QQmlProfilerService::Event) { - int event; - stream >> event; - - if (event == QQmlProfilerService::EndTrace) { - emit this->traceFinished(time); - d->maximumTime = time; - d->maximumTime = qMax(time, d->maximumTime); - } else if (event == QQmlProfilerService::AnimationFrame) { - int frameRate, animationCount; - stream >> frameRate >> animationCount; - emit this->frame(time, frameRate, animationCount); - d->maximumTime = qMax(time, d->maximumTime); - } else if (event == QQmlProfilerService::StartTrace) { - emit this->traceStarted(time); - d->maximumTime = time; - } else if (event < QQmlProfilerService::MaximumEventType) { - d->maximumTime = qMax(time, d->maximumTime); - } - } else if (messageType == QQmlProfilerService::Complete) { - emit complete(); - - } else { - int range; - stream >> range; - - if (range >= QQmlProfilerService::MaximumRangeType) - return; - - if (messageType == QQmlProfilerService::RangeStart) { - d->rangeStartTimes[range].push(time); - d->inProgressRanges |= (static_cast(1) << range); - ++d->rangeCount[range]; - } else if (messageType == QQmlProfilerService::RangeData) { - QString data; - stream >> data; - - int count = d->rangeCount[range]; - if (count > 0) { - while (d->rangeDatas[range].count() < count) - d->rangeDatas[range].push(QStringList()); - d->rangeDatas[range][count-1] << data; - } - - } else if (messageType == QQmlProfilerService::RangeLocation) { - QString fileName; - int line; - int column = -1; - stream >> fileName >> line; - - if (!stream.atEnd()) - stream >> column; - - if (d->rangeCount[range] > 0) { - d->rangeLocations[range].push(EventLocation(fileName, line, - column)); - } - } else { - if (d->rangeCount[range] > 0) { - --d->rangeCount[range]; - if (d->inProgressRanges & (static_cast(1) << range)) - d->inProgressRanges &= ~(static_cast(1) << range); - - d->maximumTime = qMax(time, d->maximumTime); - QStringList data = d->rangeDatas[range].count() ? - d->rangeDatas[range].pop() : QStringList(); - EventLocation location = d->rangeLocations[range].count() ? - d->rangeLocations[range].pop() : EventLocation(); - - qint64 startTime = d->rangeStartTimes[range].pop(); - emit this->range((QQmlProfilerService::RangeType)range, - startTime, time - startTime, data, location); - if (d->rangeCount[range] == 0) { - int count = d->rangeDatas[range].count() + - d->rangeStartTimes[range].count() + - d->rangeLocations[range].count(); - if (count != 0) - qWarning() << "incorrectly nested data"; - } - } - } - } -} - -V8ProfileClient::V8ProfileClient(QQmlDebugConnection *client) - : ProfileClient(QLatin1String("V8Profiler"), client) -{ -} - -V8ProfileClient::~V8ProfileClient() -{ -} - -void V8ProfileClient::sendRecordingStatus() -{ - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - QByteArray cmd("V8PROFILER"); - QByteArray option(""); - QByteArray title(""); - - if (m_recording) { - option = "start"; - } else { - option = "stop"; - } - stream << cmd << option << title; - sendMessage(ba); -} - -void V8ProfileClient::messageReceived(const QByteArray &data) -{ - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - int messageType; - - stream >> messageType; - - if (messageType == V8Complete) { - emit complete(); - } else if (messageType == V8Entry) { - QString filename; - QString function; - int lineNumber; - double totalTime; - double selfTime; - int depth; - - stream >> filename >> function >> lineNumber >> totalTime >> - selfTime >> depth; - emit this->range(depth, function, filename, lineNumber, totalTime, - selfTime); - } -} - diff --git a/tools/qmlprofiler/profileclient.h b/tools/qmlprofiler/profileclient.h deleted file mode 100644 index 54826a291a..0000000000 --- a/tools/qmlprofiler/profileclient.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PROFILECLIENT_H -#define PROFILECLIENT_H - -#include "profiledata.h" - -#include "qqmldebugclient.h" -#include - -class ProfileClientPrivate; -class ProfileClient : public QQmlDebugClient -{ - Q_OBJECT - - Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool recording READ isRecording WRITE setRecording - NOTIFY recordingChanged) - -public: - ProfileClient(const QString & clientName, - QQmlDebugConnection *client); - ~ProfileClient(); - - bool isEnabled() const; - bool isRecording() const; - -public slots: - void setRecording(bool); - virtual void clearData(); - virtual void sendRecordingStatus(); - -signals: - void complete(); - void recordingChanged(bool arg); - void enabledChanged(); - void cleared(); - -protected: - virtual void stateChanged(State); - -protected: - bool m_recording; - bool m_enabled; -}; - -class QmlProfileClient : public ProfileClient -{ - Q_OBJECT - -public: - QmlProfileClient(QQmlDebugConnection *client); - ~QmlProfileClient(); - -public slots: - void clearData(); - void sendRecordingStatus(); - -signals: - void traceFinished( qint64 time ); - void traceStarted( qint64 time ); - void range(QQmlProfilerService::RangeType type, qint64 startTime, - qint64 length, const QStringList &data, - const EventLocation &location); - void frame(qint64 time, int frameRate, int animationCount); - -protected: - virtual void messageReceived(const QByteArray &); - -private: - class QmlProfileClientPrivate *d; -}; - -class V8ProfileClient : public ProfileClient -{ - Q_OBJECT - -public: - enum Message { - V8Entry, - V8Complete, - - V8MaximumMessage - }; - - V8ProfileClient(QQmlDebugConnection *client); - ~V8ProfileClient(); - -public slots: - void sendRecordingStatus(); - -signals: - void range(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime); - -protected: - virtual void messageReceived(const QByteArray &); -}; - -#endif // PROFILECLIENT_H diff --git a/tools/qmlprofiler/profiledata.cpp b/tools/qmlprofiler/profiledata.cpp deleted file mode 100644 index 6082f4aa94..0000000000 --- a/tools/qmlprofiler/profiledata.cpp +++ /dev/null @@ -1,1902 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "profiledata.h" -#include "constants.h" - -#include -#include -#include -#include -#include - -using namespace Constants; - -QmlEvent::QmlEvent() -{ - eventType = QQmlProfilerService::MaximumRangeType; - eventId = -1; - duration = 0; - calls = 0; - minTime = 0; - maxTime = 0; - timePerCall = 0; - percentOfTime = 0; - medianTime = 0; - isBindingLoop = false; -} - -QmlEvent::~QmlEvent() -{ - qDeleteAll(parentHash.values()); - parentHash.clear(); - qDeleteAll(childrenHash.values()); - childrenHash.clear(); -} - -QmlEvent &QmlEvent::operator=(const QmlEvent &ref) -{ - if (this == &ref) - return *this; - - displayname = ref.displayname; - location = ref.location; - eventHashStr = ref.eventHashStr; - details = ref.details; - eventType = ref.eventType; - duration = ref.duration; - calls = ref.calls; - minTime = ref.minTime; - maxTime = ref.maxTime; - timePerCall = ref.timePerCall; - percentOfTime = ref.percentOfTime; - medianTime = ref.medianTime; - eventId = ref.eventId; - isBindingLoop = ref.isBindingLoop; - - qDeleteAll(parentHash.values()); - parentHash.clear(); - foreach (const QString &key, ref.parentHash.keys()) { - parentHash.insert(key, - new QmlEventSub(ref.parentHash.value(key))); - } - - qDeleteAll(childrenHash.values()); - childrenHash.clear(); - foreach (const QString &key, ref.childrenHash.keys()) { - childrenHash.insert(key, - new QmlEventSub(ref.childrenHash.value(key))); - } - - return *this; -} - -V8Event::V8Event() -{ - line = -1; - eventId = -1; - totalTime = 0; - selfTime = 0; - totalPercent = 0; - selfPercent = 0; -} - -V8Event::~V8Event() -{ - qDeleteAll(parentHash.values()); - parentHash.clear(); - qDeleteAll(childrenHash.values()); - childrenHash.clear(); -} - -V8Event &V8Event::operator=(const V8Event &ref) -{ - if (this == &ref) - return *this; - - displayName = ref.displayName; - filename = ref.filename; - functionName = ref.functionName; - line = ref.line; - totalTime = ref.totalTime; - totalPercent = ref.totalPercent; - selfTime = ref.selfTime; - selfPercent = ref.selfPercent; - eventId = ref.eventId; - - qDeleteAll(parentHash.values()); - parentHash.clear(); - foreach (const QString &key, ref.parentHash.keys()) { - parentHash.insert(key, new V8EventSub(ref.parentHash.value(key))); - } - - qDeleteAll(childrenHash.values()); - childrenHash.clear(); - foreach (const QString &key, ref.childrenHash.keys()) { - childrenHash.insert(key, new V8EventSub(ref.childrenHash.value(key))); - } - return *this; -} - -// endtimedata -struct QmlEventEndTime { - qint64 endTime; - int startTimeIndex; - QmlEvent *description; -}; - -// starttimedata -struct QmlEventStartTime{ - qint64 startTime; - qint64 length; - qint64 level; - int endTimeIndex; - qint64 nestingLevel; - qint64 nestingDepth; - QmlEvent *description; - - // animation-related data - int frameRate; - int animationCount; - - int bindingLoopHead; -}; - -struct QmlEventTypeCount { - QList eventIds; - int nestingCount; -}; - -// used by quicksort -bool compareEndTimes(const QmlEventEndTime &t1, - const QmlEventEndTime &t2) -{ - return t1.endTime < t2.endTime; -} - -bool compareStartTimes(const QmlEventStartTime &t1, - const QmlEventStartTime &t2) -{ - return t1.startTime < t2.startTime; -} - -bool compareStartIndexes(const QmlEventEndTime &t1, - const QmlEventEndTime &t2) -{ - return t1.startTimeIndex < t2.startTimeIndex; -} - -QString qmlEventType(QQmlProfilerService::RangeType typeEnum) -{ - switch (typeEnum) { - case QQmlProfilerService::Painting: - return QLatin1String(TYPE_PAINTING_STR); - break; - case QQmlProfilerService::Compiling: - return QLatin1String(TYPE_COMPILING_STR); - break; - case QQmlProfilerService::Creating: - return QLatin1String(TYPE_CREATING_STR); - break; - case QQmlProfilerService::Binding: - return QLatin1String(TYPE_BINDING_STR); - break; - case QQmlProfilerService::HandlingSignal: - return QLatin1String(TYPE_HANDLINGSIGNAL_STR); - break; - default: - return QString::number((int)typeEnum); - } -} - -QQmlProfilerService::RangeType qmlEventType(const QString &typeString) -{ - if (typeString == QLatin1String(TYPE_PAINTING_STR)) { - return QQmlProfilerService::Painting; - } else if (typeString == QLatin1String(TYPE_COMPILING_STR)) { - return QQmlProfilerService::Compiling; - } else if (typeString == QLatin1String(TYPE_CREATING_STR)) { - return QQmlProfilerService::Creating; - } else if (typeString == QLatin1String(TYPE_BINDING_STR)) { - return QQmlProfilerService::Binding; - } else if (typeString == QLatin1String(TYPE_HANDLINGSIGNAL_STR)) { - return QQmlProfilerService::HandlingSignal; - } else { - bool isNumber = false; - int type = typeString.toUInt(&isNumber); - if (isNumber) { - return (QQmlProfilerService::RangeType)type; - } else { - return QQmlProfilerService::MaximumRangeType; - } - } -} - -QString getHashStringForQmlEvent( - EventLocation location, - QQmlProfilerService::RangeType eventType) -{ - return QString("%1:%2:%3:%4").arg(location.filename, - QString::number(location.line), - QString::number(location.column), - QString::number(eventType)); -} - -class ProfileDataPrivate -{ -public: - - // convenience functions - void clearQmlRootEvent(); - void clearV8RootEvent(); - - // Stored data - QmlEventHash m_eventDescriptions; - QList m_endTimeSortedList; - QList m_startTimeSortedList; - - void collectV8Statistics(); - V8Events m_v8EventList; - QHash m_v8parents; - - QmlEvent m_qmlRootEvent; - V8Event m_v8RootEvent; - QString m_rootEventName; - QString m_rootEventDesc; - - QHash m_typeCounts; - - qint64 m_traceEndTime; - qint64 m_traceStartTime; - qint64 m_qmlMeasuredTime; - qint64 m_v8MeasuredTime; - - QmlEventStartTime *m_lastFrameEvent; - qint64 m_maximumAnimationCount; - qint64 m_minimumAnimationCount; - - // file to load - QString m_filename; -}; - -ProfileData::ProfileData(QObject *parent) : - QObject(parent), - d(new ProfileDataPrivate) -{ - setObjectName("ProfileData"); - - d->m_traceEndTime = 0; - d->m_traceStartTime = -1; - d->m_qmlMeasuredTime = 0; - d->m_v8MeasuredTime = 0; - d->m_rootEventName = tr(""); - d->m_rootEventDesc = tr("Main Program"); - d->clearQmlRootEvent(); - d->clearV8RootEvent(); - d->m_lastFrameEvent = 0; - d->m_maximumAnimationCount = 0; - d->m_minimumAnimationCount = 0; -} - -ProfileData::~ProfileData() -{ - clear(); -} - -void ProfileData::clear() -{ - qDeleteAll(d->m_eventDescriptions.values()); - d->m_eventDescriptions.clear(); - - qDeleteAll(d->m_v8EventList); - d->m_v8EventList.clear(); - - d->m_endTimeSortedList.clear(); - d->m_startTimeSortedList.clear(); - - d->m_v8parents.clear(); - - d->clearQmlRootEvent(); - d->clearV8RootEvent(); - - foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values()) - delete typeCount; - d->m_typeCounts.clear(); - - d->m_traceEndTime = 0; - d->m_traceStartTime = -1; - d->m_qmlMeasuredTime = 0; - d->m_v8MeasuredTime = 0; - - d->m_lastFrameEvent = 0; - d->m_maximumAnimationCount = 0; - d->m_minimumAnimationCount = 0; - - emit countChanged(); - emit dataClear(); -} - -QmlEvents ProfileData::getQmlEvents() const -{ - return d->m_eventDescriptions.values(); -} - -QmlEvent *ProfileData::qmlEvent(int eventId) const -{ - foreach (QmlEvent *event, d->m_eventDescriptions.values()) { - if (event->eventId == eventId) - return event; - } - return 0; -} - -V8Event *ProfileData::v8Event(int eventId) const -{ - foreach (V8Event *event, d->m_v8EventList) { - if (event->eventId == eventId) - return event; - } - return 0; -} - -const V8Events& ProfileData::getV8Events() const -{ - return d->m_v8EventList; -} - -void ProfileData::addQmlEvent( - QQmlProfilerService::RangeType type, qint64 startTime, qint64 length, - const QStringList &data, const EventLocation &location) -{ - const QChar colon = QLatin1Char(':'); - QString displayName, eventHashStr, details; - EventLocation eventLocation = location; - - emit processingData(); - - // generate details string - if (data.isEmpty()) - details = tr("Source code not available"); - else { - details = data.join(" ").replace('\n'," ").simplified(); - QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)"); - bool match = rewrite.exactMatch(details); - if (match) { - details = rewrite.cap(1) + ": " + rewrite.cap(3); - } - if (details.startsWith(QString("file://"))) - details = details.mid(details.lastIndexOf(QChar('/')) + 1); - } - - // backwards compatibility: "compiling" events don't have a proper location in older - // version of the protocol, but the filename is passed in the details string - if (type == QQmlProfilerService::Compiling && eventLocation.filename.isEmpty()) { - eventLocation.filename = details; - eventLocation.line = 1; - eventLocation.column = 1; - } - - // generate hash - if (eventLocation.filename.isEmpty()) { - displayName = tr(""); - eventHashStr = getHashStringForQmlEvent(eventLocation, type); - } else { - const QString filePath = QUrl(eventLocation.filename).path(); - displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(eventLocation.line); - eventHashStr = getHashStringForQmlEvent(eventLocation, type); - } - - QmlEvent *newEvent; - if (d->m_eventDescriptions.contains(eventHashStr)) { - newEvent = d->m_eventDescriptions[eventHashStr]; - } else { - newEvent = new QmlEvent; - newEvent->displayname = displayName; - newEvent->location = eventLocation; - newEvent->eventHashStr = eventHashStr; - newEvent->eventType = type; - newEvent->details = details; - d->m_eventDescriptions.insert(eventHashStr, newEvent); - } - - QmlEventEndTime endTimeData; - endTimeData.endTime = startTime + length; - endTimeData.description = newEvent; - endTimeData.startTimeIndex = d->m_startTimeSortedList.count(); - - QmlEventStartTime startTimeData; - startTimeData.startTime = startTime; - startTimeData.length = length; - startTimeData.description = newEvent; - startTimeData.endTimeIndex = d->m_endTimeSortedList.count(); - startTimeData.animationCount = -1; - startTimeData.frameRate = 1e9/length; - - d->m_endTimeSortedList << endTimeData; - d->m_startTimeSortedList << startTimeData; - - emit countChanged(); -} - -void ProfileData::addV8Event(int depth, const QString &function, - const QString &filename, int lineNumber, - double totalTime, double selfTime) -{ - QString displayName = filename.mid( - filename.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + - QString::number(lineNumber); - V8Event *eventData = 0; - - // time is given in milliseconds, but internally we store it in microseconds - totalTime *= 1e6; - selfTime *= 1e6; - - // cumulate information - foreach (V8Event *v8event, d->m_v8EventList) { - if (v8event->displayName == displayName && - v8event->functionName == function) { - eventData = v8event; - break; - } - } - - if (!eventData) { - eventData = new V8Event; - eventData->displayName = displayName; - eventData->filename = filename; - eventData->functionName = function; - eventData->line = lineNumber; - eventData->totalTime = totalTime; - eventData->selfTime = selfTime; - d->m_v8EventList << eventData; - } else { - eventData->totalTime += totalTime; - eventData->selfTime += selfTime; - } - d->m_v8parents[depth] = eventData; - - V8Event *parentEvent = 0; - if (depth == 0) { - parentEvent = &d->m_v8RootEvent; - d->m_v8MeasuredTime += totalTime; - } - if (depth > 0 && d->m_v8parents.contains(depth-1)) { - parentEvent = d->m_v8parents.value(depth-1); - } - - if (parentEvent != 0) { - if (!eventData->parentHash.contains(parentEvent->displayName)) { - V8EventSub *newParentSub = new V8EventSub(parentEvent); - newParentSub->totalTime = totalTime; - - eventData->parentHash.insert(parentEvent->displayName, newParentSub ); - } else { - V8EventSub *newParentSub = - eventData->parentHash.value(parentEvent->displayName); - newParentSub->totalTime += totalTime; - } - - if (!parentEvent->childrenHash.contains(eventData->displayName)) { - V8EventSub *newChildSub = new V8EventSub(eventData); - newChildSub->totalTime = totalTime; - - parentEvent->childrenHash.insert(eventData->displayName, newChildSub); - } else { - V8EventSub *newChildSub = - parentEvent->childrenHash.value(eventData->displayName); - newChildSub->totalTime += totalTime; - } - } -} - -void ProfileData::addFrameEvent(qint64 time, int framerate, int animationcount) -{ - QString displayName, eventHashStr, details; - - emit processingData(); - - details = tr("Animation Timer Update"); - displayName = tr(""); - eventHashStr = displayName; - - QmlEvent *newEvent; - if (d->m_eventDescriptions.contains(eventHashStr)) { - newEvent = d->m_eventDescriptions[eventHashStr]; - } else { - newEvent = new QmlEvent; - newEvent->displayname = displayName; - newEvent->eventHashStr = eventHashStr; - newEvent->eventType = QQmlProfilerService::Painting; - newEvent->details = details; - d->m_eventDescriptions.insert(eventHashStr, newEvent); - } - - qint64 length = 1e9/framerate; - // avoid overlap - if (d->m_lastFrameEvent && - d->m_lastFrameEvent->startTime + d->m_lastFrameEvent->length >= time) { - d->m_lastFrameEvent->length = time - 1 - d->m_lastFrameEvent->startTime; - d->m_endTimeSortedList[d->m_lastFrameEvent->endTimeIndex].endTime = - d->m_lastFrameEvent->startTime + d->m_lastFrameEvent->length; - } - - QmlEventEndTime endTimeData; - endTimeData.endTime = time + length; - endTimeData.description = newEvent; - endTimeData.startTimeIndex = d->m_startTimeSortedList.count(); - - QmlEventStartTime startTimeData; - startTimeData.startTime = time; - startTimeData.length = length; - startTimeData.description = newEvent; - startTimeData.endTimeIndex = d->m_endTimeSortedList.count(); - startTimeData.animationCount = animationcount; - startTimeData.frameRate = framerate; - - d->m_endTimeSortedList << endTimeData; - d->m_startTimeSortedList << startTimeData; - - d->m_lastFrameEvent = &d->m_startTimeSortedList.last(); - - emit countChanged(); -} - -void ProfileDataPrivate::collectV8Statistics() -{ - if (!m_v8EventList.isEmpty()) { - double totalTimes = m_v8MeasuredTime; - double selfTimes = 0; - foreach (V8Event *v8event, m_v8EventList) { - selfTimes += v8event->selfTime; - } - - // prevent divisions by 0 - if (totalTimes == 0) - totalTimes = 1; - if (selfTimes == 0) - selfTimes = 1; - - // insert root event in eventlist - // the +1 ns is to get it on top of the sorted list - m_v8RootEvent.totalTime = m_v8MeasuredTime + 1; - m_v8RootEvent.selfTime = 0; - - int rootEventIndex = -1; - for (int ndx = 0; ndx < m_v8EventList.count(); ndx++) - { - if (m_v8EventList.at(ndx)->displayName == m_rootEventName) { - m_v8RootEvent = *m_v8EventList.at(ndx); - rootEventIndex = ndx; - break; - } - } - if (rootEventIndex == -1) { - rootEventIndex = m_v8EventList.count(); - V8Event *newRootEvent = new V8Event; - *newRootEvent = m_v8RootEvent; - m_v8EventList << newRootEvent; - } - - foreach (V8Event *v8event, m_v8EventList) { - v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; - v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes; - } - - int index = 0; - foreach (V8Event *v8event, m_v8EventList) { - v8event->eventId = index++; - } - m_v8RootEvent.eventId = m_v8EventList[rootEventIndex]->eventId; - } -} - -void ProfileData::setTraceEndTime( qint64 time ) -{ - d->m_traceEndTime = time; -} - -void ProfileData::setTraceStartTime( qint64 time ) -{ - d->m_traceStartTime = time; -} - -void ProfileData::complete() -{ - emit postProcessing(); - d->collectV8Statistics(); - postProcess(); -} - -void ProfileDataPrivate::clearQmlRootEvent() -{ - m_qmlRootEvent.displayname = m_rootEventName; - m_qmlRootEvent.location = EventLocation(); - m_qmlRootEvent.eventHashStr = m_rootEventName; - m_qmlRootEvent.details = m_rootEventDesc; - m_qmlRootEvent.eventType = QQmlProfilerService::Binding; - m_qmlRootEvent.duration = 0; - m_qmlRootEvent.calls = 0; - m_qmlRootEvent.minTime = 0; - m_qmlRootEvent.maxTime = 0; - m_qmlRootEvent.timePerCall = 0; - m_qmlRootEvent.percentOfTime = 0; - m_qmlRootEvent.medianTime = 0; - m_qmlRootEvent.eventId = -1; - - qDeleteAll(m_qmlRootEvent.parentHash.values()); - qDeleteAll(m_qmlRootEvent.childrenHash.values()); - m_qmlRootEvent.parentHash.clear(); - m_qmlRootEvent.childrenHash.clear(); -} - -void ProfileDataPrivate::clearV8RootEvent() -{ - m_v8RootEvent.displayName = m_rootEventName; - m_v8RootEvent.functionName = m_rootEventDesc; - m_v8RootEvent.line = -1; - m_v8RootEvent.totalTime = 0; - m_v8RootEvent.totalPercent = 0; - m_v8RootEvent.selfTime = 0; - m_v8RootEvent.selfPercent = 0; - m_v8RootEvent.eventId = -1; - - qDeleteAll(m_v8RootEvent.parentHash.values()); - qDeleteAll(m_v8RootEvent.childrenHash.values()); - m_v8RootEvent.parentHash.clear(); - m_v8RootEvent.childrenHash.clear(); -} - -void ProfileData::compileStatistics(qint64 startTime, qint64 endTime) -{ - int index; - int fromIndex = findFirstIndex(startTime); - int toIndex = findLastIndex(endTime); - double totalTime = 0; - - // clear existing statistics - foreach (QmlEvent *eventDescription, - d->m_eventDescriptions.values()) { - eventDescription->calls = 0; - // maximum possible value - eventDescription->minTime = d->m_endTimeSortedList.last().endTime; - eventDescription->maxTime = 0; - eventDescription->medianTime = 0; - eventDescription->duration = 0; - qDeleteAll(eventDescription->parentHash); - qDeleteAll(eventDescription->childrenHash); - eventDescription->parentHash.clear(); - eventDescription->childrenHash.clear(); - } - - // create root event for statistics - d->clearQmlRootEvent(); - - // compute parent-child relationship and call count - QHash lastParent; - for (index = fromIndex; index <= toIndex; index++) { - QmlEvent *eventDescription = - d->m_startTimeSortedList[index].description; - - if (d->m_startTimeSortedList[index].startTime > endTime || - d->m_startTimeSortedList[index].startTime + - d->m_startTimeSortedList[index].length < startTime) { - continue; - } - - if (eventDescription->eventType == QQmlProfilerService::Painting) { - // skip animation/paint events - continue; - } - - eventDescription->calls++; - qint64 duration = d->m_startTimeSortedList[index].length; - eventDescription->duration += duration; - if (eventDescription->maxTime < duration) - eventDescription->maxTime = duration; - if (eventDescription->minTime > duration) - eventDescription->minTime = duration; - - int level = d->m_startTimeSortedList[index].level; - - QmlEvent *parentEvent = &d->m_qmlRootEvent; - if (level > MIN_LEVEL && lastParent.contains(level-1)) { - parentEvent = lastParent[level-1]; - } - - if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) { - QmlEventSub *newParentEvent = - new QmlEventSub(parentEvent); - newParentEvent->calls = 1; - newParentEvent->duration = duration; - - eventDescription->parentHash.insert(parentEvent->eventHashStr, - newParentEvent); - } else { - QmlEventSub *newParentEvent = - eventDescription->parentHash.value(parentEvent->eventHashStr); - newParentEvent->duration += duration; - newParentEvent->calls++; - } - - if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) { - QmlEventSub *newChildEvent = - new QmlEventSub(eventDescription); - newChildEvent->calls = 1; - newChildEvent->duration = duration; - - parentEvent->childrenHash.insert(eventDescription->eventHashStr, - newChildEvent); - } else { - QmlEventSub *newChildEvent = - parentEvent->childrenHash.value(eventDescription->eventHashStr); - newChildEvent->duration += duration; - newChildEvent->calls++; - } - - lastParent[level] = eventDescription; - - if (level == MIN_LEVEL) { - totalTime += duration; - } - } - - // fake rootEvent statistics - // the +1 nanosecond is to force it to be on top of the sorted list - d->m_qmlRootEvent.duration = totalTime+1; - d->m_qmlRootEvent.minTime = totalTime+1; - d->m_qmlRootEvent.maxTime = totalTime+1; - d->m_qmlRootEvent.medianTime = totalTime+1; - if (totalTime > 0) - d->m_qmlRootEvent.calls = 1; - - // insert into list - QmlEvent *listedRootEvent = - d->m_eventDescriptions.value(d->m_rootEventName); - if (!listedRootEvent) { - listedRootEvent = new QmlEvent; - d->m_eventDescriptions.insert(d->m_rootEventName, listedRootEvent); - } - *listedRootEvent = d->m_qmlRootEvent; - - // compute percentages - foreach (QmlEvent *binding, d->m_eventDescriptions.values()) { - binding->percentOfTime = binding->duration * 100.0 / totalTime; - binding->timePerCall = binding->calls > 0 ? - double(binding->duration) / binding->calls : 0; - } - - // compute median time - QHash < QmlEvent* , QList > durationLists; - for (index = fromIndex; index <= toIndex; index++) { - QmlEvent *desc = d->m_startTimeSortedList[index].description; - qint64 len = d->m_startTimeSortedList[index].length; - durationLists[desc].append(len); - } - QMutableHashIterator < QmlEvent* , QList > iter(durationLists); - while (iter.hasNext()) { - iter.next(); - if (!iter.value().isEmpty()) { - qSort(iter.value()); - iter.key()->medianTime = iter.value().at(iter.value().count()/2); - } - } -} - -void ProfileData::prepareForDisplay() -{ - // generate numeric ids - int ndx = 0; - foreach (QmlEvent *binding, d->m_eventDescriptions.values()) { - binding->eventId = ndx++; - } - - // collect type counts - foreach (const QmlEventStartTime &eventStartData, - d->m_startTimeSortedList) { - int typeNumber = eventStartData.description->eventType; - if (!d->m_typeCounts.contains(typeNumber)) { - d->m_typeCounts[typeNumber] = new QmlEventTypeCount; - d->m_typeCounts[typeNumber]->nestingCount = 0; - } - if (eventStartData.nestingLevel > - d->m_typeCounts[typeNumber]->nestingCount) { - d->m_typeCounts[typeNumber]->nestingCount = eventStartData.nestingLevel; - } - if (!d->m_typeCounts[typeNumber]->eventIds.contains( - eventStartData.description->eventId)) - d->m_typeCounts[typeNumber]->eventIds << eventStartData.description->eventId; - } -} - -void ProfileData::sortStartTimes() -{ - if (d->m_startTimeSortedList.count() < 2) - return; - - // assuming startTimes is partially sorted - // identify blocks of events and sort them with quicksort - QList::iterator itFrom = - d->m_startTimeSortedList.end() - 2; - QList::iterator itTo = - d->m_startTimeSortedList.end() - 1; - - while (itFrom != d->m_startTimeSortedList.begin() && - itTo != d->m_startTimeSortedList.begin()) { - // find block to sort - while ( itFrom != d->m_startTimeSortedList.begin() - && itTo->startTime > itFrom->startTime ) { - itTo--; - itFrom = itTo - 1; - } - - // if we're at the end of the list - if (itFrom == d->m_startTimeSortedList.begin()) - break; - - // find block length - while ( itFrom != d->m_startTimeSortedList.begin() - && itTo->startTime <= itFrom->startTime ) - itFrom--; - - if (itTo->startTime <= itFrom->startTime) - qSort(itFrom, itTo + 1, compareStartTimes); - else - qSort(itFrom + 1, itTo + 1, compareStartTimes); - - // move to next block - itTo = itFrom; - itFrom = itTo - 1; - } - - // link back the endTimes - for (int i = 0; i < d->m_startTimeSortedList.length(); i++) - d->m_endTimeSortedList[d->m_startTimeSortedList[i].endTimeIndex].startTimeIndex = i; -} - -void ProfileData::sortEndTimes() -{ - // assuming endTimes is partially sorted - // identify blocks of events and sort them with quicksort - - if (d->m_endTimeSortedList.count() < 2) - return; - - QList::iterator itFrom = - d->m_endTimeSortedList.begin(); - QList::iterator itTo = - d->m_endTimeSortedList.begin() + 1; - - while (itTo != d->m_endTimeSortedList.end() && - itFrom != d->m_endTimeSortedList.end()) { - // find block to sort - while ( itTo != d->m_endTimeSortedList.end() - && d->m_startTimeSortedList[itTo->startTimeIndex].startTime > - d->m_startTimeSortedList[itFrom->startTimeIndex].startTime + - d->m_startTimeSortedList[itFrom->startTimeIndex].length ) { - itFrom++; - itTo = itFrom+1; - } - - // if we're at the end of the list - if (itTo == d->m_endTimeSortedList.end()) - break; - - // find block length - while ( itTo != d->m_endTimeSortedList.end() - && d->m_startTimeSortedList[itTo->startTimeIndex].startTime <= - d->m_startTimeSortedList[itFrom->startTimeIndex].startTime + - d->m_startTimeSortedList[itFrom->startTimeIndex].length ) - itTo++; - - // sort block - qSort(itFrom, itTo, compareEndTimes); - - // move to next block - itFrom = itTo; - itTo = itFrom+1; - - } - - // link back the startTimes - for (int i = 0; i < d->m_endTimeSortedList.length(); i++) - d->m_startTimeSortedList[d->m_endTimeSortedList[i].startTimeIndex].endTimeIndex = i; -} - -void ProfileData::findAnimationLimits() -{ - d->m_maximumAnimationCount = 0; - d->m_minimumAnimationCount = 0; - d->m_lastFrameEvent = 0; - - for (int i = 0; i < d->m_startTimeSortedList.count(); i++) { - if (d->m_startTimeSortedList[i].description->eventType == - QQmlProfilerService::Painting && - d->m_startTimeSortedList[i].animationCount >= 0) { - int animationcount = d->m_startTimeSortedList[i].animationCount; - if (d->m_lastFrameEvent) { - if (animationcount > d->m_maximumAnimationCount) - d->m_maximumAnimationCount = animationcount; - if (animationcount < d->m_minimumAnimationCount) - d->m_minimumAnimationCount = animationcount; - } else { - d->m_maximumAnimationCount = animationcount; - d->m_minimumAnimationCount = animationcount; - } - d->m_lastFrameEvent = &d->m_startTimeSortedList[i]; - } - } -} - -void ProfileData::computeNestingLevels() -{ - // compute levels - QHash endtimesPerLevel; - QList nestingLevels; - QList < QHash > endtimesPerNestingLevel; - int level = MIN_LEVEL; - endtimesPerLevel[MIN_LEVEL] = 0; - - for (int i = 0; i < QQmlProfilerService::MaximumRangeType; i++) { - nestingLevels << MIN_LEVEL; - QHash dummyHash; - dummyHash[MIN_LEVEL] = 0; - endtimesPerNestingLevel << dummyHash; - } - - for (int i=0; im_startTimeSortedList.count(); i++) { - qint64 st = d->m_startTimeSortedList[i].startTime; - int type = d->m_startTimeSortedList[i].description->eventType; - - if (type == QQmlProfilerService::Painting) { - // animation/paint events have level 1 by definition, - // but are not considered parents of other events for - // statistical purposes - d->m_startTimeSortedList[i].level = MIN_LEVEL; - d->m_startTimeSortedList[i].nestingLevel = MIN_LEVEL; - continue; - } - - // general level - if (endtimesPerLevel[level] > st) { - level++; - } else { - while (level > MIN_LEVEL && endtimesPerLevel[level-1] <= st) - level--; - } - endtimesPerLevel[level] = st + d->m_startTimeSortedList[i].length; - - // per type - if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) { - nestingLevels[type]++; - } else { - while (nestingLevels[type] > MIN_LEVEL && - endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st) - nestingLevels[type]--; - } - endtimesPerNestingLevel[type][nestingLevels[type]] = st + - d->m_startTimeSortedList[i].length; - - d->m_startTimeSortedList[i].level = level; - d->m_startTimeSortedList[i].nestingLevel = nestingLevels[type]; - - if (level == MIN_LEVEL) { - d->m_qmlMeasuredTime += d->m_startTimeSortedList[i].length; - } - } -} - -void ProfileData::computeNestingDepth() -{ - QHash nestingDepth; - for (int i = 0; i < d->m_endTimeSortedList.count(); i++) { - int type = d->m_endTimeSortedList[i].description->eventType; - int nestingInType = d->m_startTimeSortedList[d->m_endTimeSortedList[i].startTimeIndex].nestingLevel; - if (!nestingDepth.contains(type)) - nestingDepth[type] = nestingInType; - else { - int nd = nestingDepth[type]; - nestingDepth[type] = nd > nestingInType ? nd : nestingInType; - } - - d->m_startTimeSortedList[d->m_endTimeSortedList[i].startTimeIndex].nestingDepth - = nestingDepth[type]; - if (nestingInType == MIN_LEVEL) - nestingDepth[type] = MIN_LEVEL; - } -} - -void ProfileData::postProcess() -{ - if (count() != 0) { - sortStartTimes(); - sortEndTimes(); - findAnimationLimits(); - computeLevels(); - linkEndsToStarts(); - reloadDetails(); - compileStatistics(traceStartTime(), traceEndTime()); - prepareForDisplay(); - } - // data is ready even when there's no data - emit dataReady(); -} - -void ProfileData::linkEndsToStarts() -{ - for (int i = 0; i < d->m_startTimeSortedList.count(); i++) - d->m_endTimeSortedList[d->m_startTimeSortedList[i].endTimeIndex].startTimeIndex = i; -} - -void ProfileData::computeLevels() -{ - computeNestingLevels(); - computeNestingDepth(); -} - -void ProfileData::reloadDetails() -{ - // request binding/signal details from the AST - foreach (QmlEvent *event, d->m_eventDescriptions.values()) { - if (event->eventType != QQmlProfilerService::Binding && - event->eventType != QQmlProfilerService::HandlingSignal) - continue; - - // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them) - if (event->location.filename.isEmpty()) - continue; - - // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them) - if (event->location.column == -1) - continue; - - emit requestDetailsForLocation(event->eventType, event->location); - } - emit reloadDocumentsForDetails(); -} - -void ProfileData::findBindingLoops(qint64 startTime, qint64 endTime) -{ - // first clear existing data - foreach (QmlEvent *event, d->m_eventDescriptions.values()) { - event->isBindingLoop = false; - foreach (QmlEventSub *parentEvent, event->parentHash.values()) - parentEvent->inLoopPath = false; - foreach (QmlEventSub *childEvent, event->childrenHash.values()) - childEvent->inLoopPath = false; - } - - QList stackRefs; - QList stack; - int fromIndex = findFirstIndex(startTime); - int toIndex = findLastIndex(endTime); - - for (int i = 0; i < d->m_startTimeSortedList.count(); i++) { - QmlEvent *currentEvent = d->m_startTimeSortedList[i].description; - QmlEventStartTime *inTimeEvent = &d->m_startTimeSortedList[i]; - inTimeEvent->bindingLoopHead = -1; - - // managing call stack - for (int j = stack.count() - 1; j >= 0; j--) { - if (stack[j]->startTime + stack[j]->length <= inTimeEvent->startTime) { - stack.removeAt(j); - stackRefs.removeAt(j); - } - } - - bool loopDetected = stackRefs.contains(currentEvent); - stack << inTimeEvent; - stackRefs << currentEvent; - - if (loopDetected) { - if (i >= fromIndex && i <= toIndex) { - // for the statistics - currentEvent->isBindingLoop = true; - for (int j = stackRefs.indexOf(currentEvent); j < stackRefs.count()-1; j++) { - QmlEventSub *nextEventSub = stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr); - nextEventSub->inLoopPath = true; - QmlEventSub *prevEventSub = stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr); - prevEventSub->inLoopPath = true; - } - } - - // use crossed references to find index in starttimesortedlist - QmlEventStartTime *head = stack[stackRefs.indexOf(currentEvent)]; - inTimeEvent->bindingLoopHead = d->m_endTimeSortedList[head->endTimeIndex].startTimeIndex; - d->m_startTimeSortedList[inTimeEvent->bindingLoopHead].bindingLoopHead = i; - } - } -} - -void ProfileData::rewriteDetailsString( - QQmlProfilerService::RangeType eventType, - const EventLocation &location, const QString &newString) -{ - QString eventHashStr = getHashStringForQmlEvent(location, - eventType); - Q_ASSERT(d->m_eventDescriptions.contains(eventHashStr)); - d->m_eventDescriptions.value(eventHashStr)->details = newString; - emit detailsChanged(d->m_eventDescriptions.value(eventHashStr)->eventId, - newString); -} - -void ProfileData::finishedRewritingDetails() -{ - emit reloadDetailLabels(); -} - -// get list of events between A and B: -// find fist event with endtime after A -> aa -// find last event with starttime before B -> bb -// list is from parent of aa with level=0 to bb, in the "sorted by starttime" list -int ProfileData::findFirstIndex(qint64 startTime) const -{ - int candidate = -1; - // in the "endtime" list, find the first event that ends after startTime - if (d->m_endTimeSortedList.isEmpty()) - return 0; // -1 - if (d->m_endTimeSortedList.length() == 1 || - d->m_endTimeSortedList.first().endTime >= startTime) - candidate = 0; - else - if (d->m_endTimeSortedList.last().endTime <= startTime) - return 0; // -1 - - if (candidate == -1) - { - int fromIndex = 0; - int toIndex = d->m_endTimeSortedList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->m_endTimeSortedList[midIndex].endTime < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - candidate = toIndex; - } - - int ndx = d->m_endTimeSortedList[candidate].startTimeIndex; - - // and then go to the parent - while (d->m_startTimeSortedList[ndx].level != MIN_LEVEL && ndx > 0) - ndx--; - - return ndx; -} - -int ProfileData::findFirstIndexNoParents(qint64 startTime) const -{ - int candidate = -1; - // in the "endtime" list, find the first event that ends after startTime - if (d->m_endTimeSortedList.isEmpty()) - return 0; // -1 - if (d->m_endTimeSortedList.length() == 1 || - d->m_endTimeSortedList.first().endTime >= startTime) - candidate = 0; - else - if (d->m_endTimeSortedList.last().endTime <= startTime) - return 0; // -1 - - if (candidate == -1) { - int fromIndex = 0; - int toIndex = d->m_endTimeSortedList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->m_endTimeSortedList[midIndex].endTime < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - candidate = toIndex; - } - - int ndx = d->m_endTimeSortedList[candidate].startTimeIndex; - - return ndx; -} - -int ProfileData::findLastIndex(qint64 endTime) const -{ - // in the "starttime" list, find the last event that starts before endtime - if (d->m_startTimeSortedList.isEmpty()) - return 0; // -1 - if (d->m_startTimeSortedList.first().startTime >= endTime) - return 0; // -1 - if (d->m_startTimeSortedList.length() == 1) - return 0; - if (d->m_startTimeSortedList.last().startTime <= endTime) - return d->m_startTimeSortedList.count()-1; - - int fromIndex = 0; - int toIndex = d->m_startTimeSortedList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->m_startTimeSortedList[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - return fromIndex; -} - -qint64 ProfileData::firstTimeMark() const -{ - if (d->m_startTimeSortedList.isEmpty()) - return 0; - else { - return d->m_startTimeSortedList[0].startTime; - } -} - -qint64 ProfileData::lastTimeMark() const -{ - if (d->m_endTimeSortedList.isEmpty()) - return 0; - else { - return d->m_endTimeSortedList.last().endTime; - } -} - -qint64 ProfileData::traceStartTime() const -{ - return d->m_traceStartTime != -1? d->m_traceStartTime : firstTimeMark(); -} - -qint64 ProfileData::traceEndTime() const -{ - return d->m_traceEndTime ? d->m_traceEndTime : lastTimeMark(); -} - -qint64 ProfileData::traceDuration() const -{ - return traceEndTime() - traceStartTime(); -} - -qint64 ProfileData::qmlMeasuredTime() const -{ - return d->m_qmlMeasuredTime; -} -qint64 ProfileData::v8MeasuredTime() const -{ - return d->m_v8MeasuredTime; -} - -int ProfileData::count() const -{ - return d->m_startTimeSortedList.count(); -} - -//////////////////////////////////////////////////////////////////////////////// - - -bool ProfileData::save(const QString &filename) -{ - if (count() == 0) { - emit error(tr("No data to save")); - return false; - } - - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - emit error(tr("Could not open %1 for writing").arg(filename)); - return false; - } - - QXmlStreamWriter stream(&file); - stream.setAutoFormatting(true); - stream.writeStartDocument(); - - stream.writeStartElement("trace"); - stream.writeAttribute("version", PROFILER_FILE_VERSION); - - stream.writeAttribute("traceStart", QString::number(traceStartTime())); - stream.writeAttribute("traceEnd", QString::number(traceEndTime())); - - stream.writeStartElement("eventData"); - stream.writeAttribute("totalTime", QString::number(d->m_qmlMeasuredTime)); - - foreach (const QmlEvent *eventData, d->m_eventDescriptions.values()) { - stream.writeStartElement("event"); - stream.writeAttribute("index", - QString::number( - d->m_eventDescriptions.keys().indexOf( - eventData->eventHashStr))); - stream.writeTextElement("displayname", eventData->displayname); - stream.writeTextElement("type", qmlEventType(eventData->eventType)); - if (!eventData->location.filename.isEmpty()) { - stream.writeTextElement("filename", eventData->location.filename); - stream.writeTextElement("line", - QString::number(eventData->location.line)); - stream.writeTextElement("column", - QString::number(eventData->location.column)); - } - stream.writeTextElement("details", eventData->details); - stream.writeEndElement(); - } - stream.writeEndElement(); // eventData - - stream.writeStartElement("eventList"); - foreach (const QmlEventStartTime &rangedEvent, - d->m_startTimeSortedList) { - stream.writeStartElement("range"); - stream.writeAttribute("startTime", QString::number(rangedEvent.startTime)); - stream.writeAttribute("duration", QString::number(rangedEvent.length)); - stream.writeAttribute("eventIndex", - QString::number(d->m_eventDescriptions.keys().indexOf( - rangedEvent.description->eventHashStr))); - if (rangedEvent.description->eventType == - QQmlProfilerService::Painting && rangedEvent.animationCount >= 0) { - // animation frame - stream.writeAttribute("framerate", - QString::number(rangedEvent.frameRate)); - stream.writeAttribute("animationcount", - QString::number(rangedEvent.animationCount)); - } - stream.writeEndElement(); - } - stream.writeEndElement(); // eventList - - stream.writeStartElement("v8profile"); // v8 profiler output - stream.writeAttribute("totalTime", QString::number(d->m_v8MeasuredTime)); - foreach (V8Event *v8event, d->m_v8EventList) { - stream.writeStartElement("event"); - stream.writeAttribute("index", - QString::number(d->m_v8EventList.indexOf(v8event))); - stream.writeTextElement("displayname", v8event->displayName); - stream.writeTextElement("functionname", v8event->functionName); - if (!v8event->filename.isEmpty()) { - stream.writeTextElement("filename", v8event->filename); - stream.writeTextElement("line", QString::number(v8event->line)); - } - stream.writeTextElement("totalTime", - QString::number(v8event->totalTime)); - stream.writeTextElement("selfTime", QString::number(v8event->selfTime)); - if (!v8event->childrenHash.isEmpty()) { - stream.writeStartElement("childrenEvents"); - QStringList childrenIndexes; - QStringList childrenTimes; - QStringList parentTimes; - foreach (V8EventSub *v8child, v8event->childrenHash.values()) { - childrenIndexes << QString::number(v8child->reference->eventId); - childrenTimes << QString::number(v8child->totalTime); - parentTimes << QString::number( - d->m_v8EventList[v8child->reference->eventId]-> - parentHash[v8event->displayName]->totalTime); - } - - stream.writeAttribute("list", childrenIndexes.join(QString(", "))); - stream.writeAttribute("childrenTimes", - childrenTimes.join(QString(", "))); - stream.writeAttribute("parentTimes", - parentTimes.join(QString(", "))); - stream.writeEndElement(); - } - stream.writeEndElement(); - } - stream.writeEndElement(); // v8 profiler output - - stream.writeEndElement(); // trace - stream.writeEndDocument(); - - file.close(); - return true; -} - -void ProfileData::setFilename(const QString &filename) -{ - d->m_filename = filename; -} - -void ProfileData::load(const QString &filename) -{ - setFilename(filename); - load(); -} - -// "be strict in your output but tolerant in your inputs" -void ProfileData::load() -{ - QString filename = d->m_filename; - - QFile file(filename); - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - emit error(tr("Could not open %1 for reading").arg(filename)); - return; - } - - emit processingData(); - - // erase current - clear(); - - bool readingQmlEvents = false; - bool readingV8Events = false; - QHash descriptionBuffer; - QmlEvent *currentEvent = 0; - QHash v8eventBuffer; - QHash childrenIndexes; - QHash childrenTimes; - QHash parentTimes; - V8Event *v8event = 0; - bool startTimesAreSorted = true; - bool validVersion = true; - - // time computation - d->m_v8MeasuredTime = 0; - d->m_qmlMeasuredTime = 0; - double cumulatedV8Time = 0; - - QXmlStreamReader stream(&file); - - while (validVersion && !stream.atEnd() && !stream.hasError()) { - QXmlStreamReader::TokenType token = stream.readNext(); - QString elementName = stream.name().toString(); - switch (token) { - case QXmlStreamReader::StartDocument : continue; - case QXmlStreamReader::StartElement : { - if (elementName == "trace") { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("version")) - validVersion = - attributes.value("version").toString() == - PROFILER_FILE_VERSION; - else - validVersion = false; - if (attributes.hasAttribute("traceStart")) - setTraceStartTime(attributes.value("traceStart"). - toString().toLongLong()); - if (attributes.hasAttribute("traceEnd")) - setTraceEndTime(attributes.value("traceEnd"). - toString().toLongLong()); - } - if (elementName == "eventData" && !readingV8Events) { - readingQmlEvents = true; - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("totalTime")) - d->m_qmlMeasuredTime = attributes.value("totalTime"). - toString().toDouble(); - break; - } - if (elementName == "v8profile" && !readingQmlEvents) { - readingV8Events = true; - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("totalTime")) - d->m_v8MeasuredTime = attributes.value("totalTime"). - toString().toDouble(); - break; - } - - if (elementName == "trace") { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("traceStart")) - setTraceStartTime(attributes.value("traceStart"). - toString().toLongLong()); - if (attributes.hasAttribute("traceEnd")) - setTraceEndTime(attributes.value("traceEnd"). - toString().toLongLong()); - } - - if (elementName == "range") { - QmlEventStartTime rangedEvent; - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("startTime")) - rangedEvent.startTime = attributes.value("startTime"). - toString().toLongLong(); - if (attributes.hasAttribute("duration")) - rangedEvent.length = attributes.value("duration"). - toString().toLongLong(); - if (attributes.hasAttribute("framerate")) - rangedEvent.frameRate = attributes.value("framerate"). - toString().toInt(); - if (attributes.hasAttribute("animationcount")) - rangedEvent.animationCount = attributes.value("animationcount"). - toString().toInt(); - else - rangedEvent.animationCount = -1; - if (attributes.hasAttribute("eventIndex")) { - int ndx = attributes.value("eventIndex").toString().toInt(); - if (!descriptionBuffer.value(ndx)) - descriptionBuffer[ndx] = new QmlEvent; - rangedEvent.description = descriptionBuffer.value(ndx); - } - rangedEvent.endTimeIndex = d->m_endTimeSortedList.length(); - - if (!d->m_startTimeSortedList.isEmpty() - && rangedEvent.startTime < - d->m_startTimeSortedList.last().startTime) - startTimesAreSorted = false; - d->m_startTimeSortedList << rangedEvent; - - QmlEventEndTime endTimeEvent; - endTimeEvent.endTime = rangedEvent.startTime + rangedEvent.length; - endTimeEvent.startTimeIndex = d->m_startTimeSortedList.length()-1; - endTimeEvent.description = rangedEvent.description; - d->m_endTimeSortedList << endTimeEvent; - break; - } - - if (readingQmlEvents) { - if (elementName == "event") { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("index")) { - int ndx = attributes.value("index").toString().toInt(); - if (!descriptionBuffer.value(ndx)) - descriptionBuffer[ndx] = new QmlEvent; - currentEvent = descriptionBuffer[ndx]; - } else { - currentEvent = 0; - } - break; - } - - // the remaining are eventdata or v8eventdata elements - if (!currentEvent) - break; - - stream.readNext(); - if (stream.tokenType() != QXmlStreamReader::Characters) - break; - QString readData = stream.text().toString(); - - if (elementName == "displayname") { - currentEvent->displayname = readData; - break; - } - if (elementName == "type") { - currentEvent->eventType = qmlEventType(readData); - break; - } - if (elementName == "filename") { - currentEvent->location.filename = readData; - break; - } - if (elementName == "line") { - currentEvent->location.line = readData.toInt(); - break; - } - if (elementName == "column") { - currentEvent->location.column = readData.toInt(); - } - if (elementName == "details") { - currentEvent->details = readData; - break; - } - } - - if (readingV8Events) { - if (elementName == "event") { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute("index")) { - int ndx = attributes.value("index").toString().toInt(); - if (!v8eventBuffer.value(ndx)) - v8eventBuffer[ndx] = new V8Event; - v8event = v8eventBuffer[ndx]; - } else { - v8event = 0; - } - break; - } - - // the remaining are eventdata or v8eventdata elements - if (!v8event) - break; - - if (elementName == "childrenEvents") { - QXmlStreamAttributes attributes = stream.attributes(); - int eventIndex = v8eventBuffer.key(v8event); - if (attributes.hasAttribute("list")) { - // store for later parsing (we haven't read all the events yet) - childrenIndexes[eventIndex] = - attributes.value("list").toString(); - } - if (attributes.hasAttribute("childrenTimes")) { - childrenTimes[eventIndex] = - attributes.value("childrenTimes").toString(); - } - if (attributes.hasAttribute("parentTimes")) { - parentTimes[eventIndex] = - attributes.value("parentTimes").toString(); - } - } - - stream.readNext(); - if (stream.tokenType() != QXmlStreamReader::Characters) - break; - QString readData = stream.text().toString(); - - if (elementName == "displayname") { - v8event->displayName = readData; - break; - } - - if (elementName == "functionname") { - v8event->functionName = readData; - break; - } - - if (elementName == "filename") { - v8event->filename = readData; - break; - } - - if (elementName == "line") { - v8event->line = readData.toInt(); - break; - } - - if (elementName == "totalTime") { - v8event->totalTime = readData.toDouble(); - cumulatedV8Time += v8event->totalTime; - break; - } - - if (elementName == "selfTime") { - v8event->selfTime = readData.toDouble(); - break; - } - } - - break; - } - case QXmlStreamReader::EndElement : { - if (elementName == "event") { - currentEvent = 0; - break; - } - if (elementName == "eventData") { - readingQmlEvents = false; - break; - } - if (elementName == "v8profile") { - readingV8Events = false; - } - } - default: break; - } - } - - file.close(); - - if (stream.hasError()) { - emit error(tr("Error while parsing %1").arg(filename)); - clear(); - return; - } - - stream.clear(); - - if (!validVersion) { - clear(); - emit countChanged(); - emit dataReady(); - emit error(tr("Invalid version of QML Trace file.")); - return; - } - - // backwards compatibility - if (d->m_v8MeasuredTime == 0) - d->m_v8MeasuredTime = cumulatedV8Time; - - // move the buffered data to the details cache - foreach (QmlEvent *desc, descriptionBuffer.values()) { - desc->eventHashStr = getHashStringForQmlEvent( - desc->location, desc->eventType);; - d->m_eventDescriptions[desc->eventHashStr] = desc; - } - - // sort startTimeSortedList - if (!startTimesAreSorted) { - qSort(d->m_startTimeSortedList.begin(), - d->m_startTimeSortedList.end(), compareStartTimes); - for (int i = 0; i< d->m_startTimeSortedList.length(); i++) { - QmlEventStartTime startTimeData = d->m_startTimeSortedList[i]; - d->m_endTimeSortedList[startTimeData.endTimeIndex].startTimeIndex = i; - } - qSort(d->m_endTimeSortedList.begin(), - d->m_endTimeSortedList.end(), compareStartIndexes); - } - - // find v8events' children and parents - foreach (int parentIndex, childrenIndexes.keys()) { - QStringList childrenStrings = - childrenIndexes.value(parentIndex).split(","); - QStringList childrenTimesStrings = - childrenTimes.value(parentIndex).split(", "); - QStringList parentTimesStrings = - parentTimes.value(parentIndex).split(", "); - for (int ndx = 0; ndx < childrenStrings.count(); ndx++) { - int childIndex = childrenStrings[ndx].toInt(); - if (v8eventBuffer.value(childIndex)) { - V8EventSub *newChild = new V8EventSub(v8eventBuffer[childIndex]); - V8EventSub *newParent = new V8EventSub(v8eventBuffer[parentIndex]); - if (childrenTimesStrings.count() > ndx) - newChild->totalTime = childrenTimesStrings[ndx].toDouble(); - if (parentTimesStrings.count() > ndx) - newParent->totalTime = parentTimesStrings[ndx].toDouble(); - v8eventBuffer[parentIndex]->childrenHash.insert( - newChild->reference->displayName, newChild); - v8eventBuffer[childIndex]->parentHash.insert( - newParent->reference->displayName, newParent); - } - } - } - // store v8 events - d->m_v8EventList = v8eventBuffer.values(); - - emit countChanged(); - - descriptionBuffer.clear(); - - emit postProcessing(); - d->collectV8Statistics(); - postProcess(); -} - -/////////////////////////////////////////////// -qint64 ProfileData::getStartTime(int index) const -{ - return d->m_startTimeSortedList[index].startTime; -} - -qint64 ProfileData::getEndTime(int index) const -{ - return d->m_startTimeSortedList[index].startTime + - d->m_startTimeSortedList[index].length; -} - -qint64 ProfileData::getDuration(int index) const -{ - return d->m_startTimeSortedList[index].length; -} - -int ProfileData::getType(int index) const -{ - return d->m_startTimeSortedList[index].description->eventType; -} - -int ProfileData::getNestingLevel(int index) const -{ - return d->m_startTimeSortedList[index].nestingLevel; -} - -int ProfileData::getNestingDepth(int index) const -{ - return d->m_startTimeSortedList[index].nestingDepth; -} - -QString ProfileData::getFilename(int index) const -{ - return d->m_startTimeSortedList[index].description->location.filename; -} - -int ProfileData::getLine(int index) const -{ - return d->m_startTimeSortedList[index].description->location.line; -} - -int ProfileData::getColumn(int index) const -{ - return d->m_startTimeSortedList[index].description->location.column; -} - -QString ProfileData::getDetails(int index) const -{ - // special: animations - if (d->m_startTimeSortedList[index].description->eventType == - QQmlProfilerService::Painting && - d->m_startTimeSortedList[index].animationCount >= 0) - return tr("%1 animations at %2 FPS").arg( - QString::number(d->m_startTimeSortedList[index].animationCount), - QString::number(d->m_startTimeSortedList[index].frameRate)); - return d->m_startTimeSortedList[index].description->details; -} - -int ProfileData::getEventId(int index) const { - return d->m_startTimeSortedList[index].description->eventId; -} - -int ProfileData::getFramerate(int index) const -{ - return d->m_startTimeSortedList[index].frameRate; -} - -int ProfileData::getAnimationCount(int index) const -{ - return d->m_startTimeSortedList[index].animationCount; -} - -int ProfileData::getMaximumAnimationCount() const -{ - return d->m_maximumAnimationCount; -} - -int ProfileData::getMinimumAnimationCount() const -{ - return d->m_minimumAnimationCount; -} - -int ProfileData::uniqueEventsOfType(int type) const -{ - if (!d->m_typeCounts.contains(type)) - return 0; - return d->m_typeCounts[type]->eventIds.count(); -} - -int ProfileData::maxNestingForType(int type) const -{ - if (!d->m_typeCounts.contains(type)) - return 0; - return d->m_typeCounts[type]->nestingCount; -} - -QString ProfileData::eventTextForType(int type, int index) const -{ - if (!d->m_typeCounts.contains(type)) - return QString(); - return d->m_eventDescriptions.values().at( - d->m_typeCounts[type]->eventIds[index])->details; -} - -QString ProfileData::eventDisplayNameForType(int type, int index) const -{ - if (!d->m_typeCounts.contains(type)) - return QString(); - return d->m_eventDescriptions.values().at( - d->m_typeCounts[type]->eventIds[index])->displayname; -} - -int ProfileData::eventIdForType(int type, int index) const -{ - if (!d->m_typeCounts.contains(type)) - return -1; - return d->m_typeCounts[type]->eventIds[index]; -} - -int ProfileData::eventPosInType(int index) const -{ - int eventType = d->m_startTimeSortedList[index].description->eventType; - return d->m_typeCounts[eventType]->eventIds.indexOf( - d->m_startTimeSortedList[index].description->eventId); -} diff --git a/tools/qmlprofiler/profiledata.h b/tools/qmlprofiler/profiledata.h deleted file mode 100644 index f5d726916c..0000000000 --- a/tools/qmlprofiler/profiledata.h +++ /dev/null @@ -1,247 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PROFILEDATA_H -#define PROFILEDATA_H - -#include - -#include -#include - -struct QmlEvent; -struct V8Event; - -typedef QHash QmlEventHash; -typedef QList QmlEvents; -typedef QList V8Events; - -struct EventLocation -{ - EventLocation() : line(-1),column(-1) {} - EventLocation(const QString &file, int lineNumber, int columnNumber) - : filename(file), line(lineNumber), column(columnNumber) {} - QString filename; - int line; - int column; -}; - -struct QmlEventSub { - QmlEventSub(QmlEvent *from) - : reference(from), duration(0), calls(0), inLoopPath(false) - {} - QmlEventSub(QmlEventSub *from) - : reference(from->reference), duration(from->duration), - calls(from->calls), inLoopPath(from->inLoopPath) - {} - QmlEvent *reference; - qint64 duration; - qint64 calls; - bool inLoopPath; -}; - -struct QmlEvent -{ - QmlEvent(); - ~QmlEvent(); - - QString displayname; - QString eventHashStr; - QString details; - EventLocation location; - QQmlProfilerService::RangeType eventType; - QHash parentHash; - QHash childrenHash; - qint64 duration; - qint64 calls; - qint64 minTime; - qint64 maxTime; - double timePerCall; - double percentOfTime; - qint64 medianTime; - int eventId; - bool isBindingLoop; - - QmlEvent &operator=(const QmlEvent &ref); -}; - -struct V8EventSub { - V8EventSub(V8Event *from) - : reference(from), totalTime(0) - {} - V8EventSub(V8EventSub *from) - : reference(from->reference), totalTime(from->totalTime) - {} - - V8Event *reference; - qint64 totalTime; -}; - -struct V8Event -{ - V8Event(); - ~V8Event(); - - QString displayName; - QString filename; - QString functionName; - int line; - double totalTime; // given in milliseconds - double totalPercent; - double selfTime; - double selfPercent; - QHash parentHash; - QHash childrenHash; - int eventId; - - V8Event &operator=(const V8Event &ref); -}; - -class ProfileData : public QObject -{ - Q_OBJECT - -public: - explicit ProfileData(QObject *parent = 0); - ~ProfileData(); - - QmlEvents getQmlEvents() const; - QmlEvent *qmlEvent(int eventId) const; - const V8Events& getV8Events() const; - V8Event *v8Event(int eventId) const; - - int findFirstIndex(qint64 startTime) const; - int findFirstIndexNoParents(qint64 startTime) const; - int findLastIndex(qint64 endTime) const; - Q_INVOKABLE qint64 firstTimeMark() const; - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE int count() const; - - // data access - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getEndTime(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE int getType(int index) const; - Q_INVOKABLE int getNestingLevel(int index) const; - Q_INVOKABLE int getNestingDepth(int index) const; - Q_INVOKABLE QString getFilename(int index) const; - Q_INVOKABLE int getLine(int index) const; - Q_INVOKABLE int getColumn(int index) const; - Q_INVOKABLE QString getDetails(int index) const; - Q_INVOKABLE int getEventId(int index) const; - Q_INVOKABLE int getFramerate(int index) const; - Q_INVOKABLE int getAnimationCount(int index) const; - Q_INVOKABLE int getMaximumAnimationCount() const; - Q_INVOKABLE int getMinimumAnimationCount() const; - - // per-type data - Q_INVOKABLE int uniqueEventsOfType(int type) const; - Q_INVOKABLE int maxNestingForType(int type) const; - Q_INVOKABLE QString eventTextForType(int type, int index) const; - Q_INVOKABLE QString eventDisplayNameForType(int type, int index) const; - Q_INVOKABLE int eventIdForType(int type, int index) const; - Q_INVOKABLE int eventPosInType(int index) const; - - Q_INVOKABLE qint64 traceStartTime() const; - Q_INVOKABLE qint64 traceEndTime() const; - Q_INVOKABLE qint64 traceDuration() const; - Q_INVOKABLE qint64 qmlMeasuredTime() const; - Q_INVOKABLE qint64 v8MeasuredTime() const; - - void showErrorDialog(const QString &st ) const; - void compileStatistics(qint64 startTime, qint64 endTime); - -signals: - void dataReady(); - void countChanged(); - void error(const QString &error); - void dataClear(); - void processingData(); - void postProcessing(); - - void requestDetailsForLocation(int eventType, const EventLocation &location); - void detailsChanged(int eventId, const QString &newString); - void reloadDetailLabels(); - void reloadDocumentsForDetails(); - -public slots: - void clear(); - void addQmlEvent(QQmlProfilerService::RangeType type, - qint64 startTime, qint64 length, - const QStringList &data, - const EventLocation &location); - void complete(); - - void addV8Event(int depth,const QString &function,const QString &filename, - int lineNumber, double totalTime, double selfTime); - void addFrameEvent(qint64 time, int framerate, int animationcount); - bool save(const QString &filename); - void load(const QString &filename); - void setFilename(const QString &filename); - void load(); - - void setTraceEndTime( qint64 time ); - void setTraceStartTime( qint64 time ); - - void rewriteDetailsString(QQmlProfilerService::RangeType eventType, - const EventLocation &location, - const QString &newString); - void finishedRewritingDetails(); - -private: - void postProcess(); - void sortEndTimes(); - void findAnimationLimits(); - void sortStartTimes(); - void computeLevels(); - void computeNestingLevels(); - void computeNestingDepth(); - void prepareForDisplay(); - void linkEndsToStarts(); - void reloadDetails(); - void findBindingLoops(qint64 startTime, qint64 endTime); - -private: - class ProfileDataPrivate *d; -}; - -#endif // PROFILEDATA_H diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro index db7e357b70..c35c487a1d 100644 --- a/tools/qmlprofiler/qmlprofiler.pro +++ b/tools/qmlprofiler/qmlprofiler.pro @@ -14,14 +14,15 @@ CONFIG += console declarative_debug SOURCES += main.cpp \ qmlprofilerapplication.cpp \ commandlistener.cpp \ - profileclient.cpp \ - profiledata.cpp \ - qqmldebugclient.cpp + qqmldebugclient.cpp \ + qmlprofilerdata.cpp \ + qmlprofilerclient.cpp HEADERS += \ qmlprofilerapplication.h \ commandlistener.h \ constants.h \ - profileclient.h \ - profiledata.h \ + qmlprofilerdata.h \ + qmlprofilerclient.h \ + qmlprofilereventlocation.h \ qqmldebugclient.h diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp index 0b10ec0b15..05518dd167 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.cpp +++ b/tools/qmlprofiler/qmlprofilerapplication.cpp @@ -104,20 +104,20 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) : connect(&m_qmlProfilerClient, SIGNAL(enabledChanged()), this, SLOT(traceClientEnabled())); connect(&m_qmlProfilerClient, SIGNAL(recordingChanged(bool)), this, SLOT(recordingChanged())); - connect(&m_qmlProfilerClient, SIGNAL(range(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)), - &m_profileData, SLOT(addQmlEvent(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation))); - connect(&m_qmlProfilerClient, SIGNAL(traceFinished(qint64)), &m_profileData, SLOT(setTraceEndTime(qint64))); - connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), &m_profileData, SLOT(setTraceStartTime(qint64))); - connect(&m_qmlProfilerClient, SIGNAL(frame(qint64,int,int)), &m_profileData, SLOT(addFrameEvent(qint64,int,int))); + connect(&m_qmlProfilerClient, SIGNAL(range(QQmlProfilerService::RangeType,qint64,qint64,QStringList,QmlEventLocation)), + &m_profilerData, SLOT(addQmlEvent(QQmlProfilerService::RangeType,qint64,qint64,QStringList,QmlEventLocation))); + connect(&m_qmlProfilerClient, SIGNAL(traceFinished(qint64)), &m_profilerData, SLOT(setTraceEndTime(qint64))); + connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), &m_profilerData, SLOT(setTraceStartTime(qint64))); + connect(&m_qmlProfilerClient, SIGNAL(frame(qint64,int,int)), &m_profilerData, SLOT(addFrameEvent(qint64,int,int))); connect(&m_qmlProfilerClient, SIGNAL(complete()), this, SLOT(qmlComplete())); connect(&m_v8profilerClient, SIGNAL(enabledChanged()), this, SLOT(profilerClientEnabled())); connect(&m_v8profilerClient, SIGNAL(range(int,QString,QString,int,double,double)), - &m_profileData, SLOT(addV8Event(int,QString,QString,int,double,double))); + &m_profilerData, SLOT(addV8Event(int,QString,QString,int,double,double))); connect(&m_v8profilerClient, SIGNAL(complete()), this, SLOT(v8Complete())); - connect(&m_profileData, SIGNAL(error(QString)), this, SLOT(logError(QString))); - connect(&m_profileData, SIGNAL(dataReady()), this, SLOT(traceFinished())); + connect(&m_profilerData, SIGNAL(error(QString)), this, SLOT(logError(QString))); + connect(&m_profilerData, SIGNAL(dataReady()), this, SLOT(traceFinished())); } @@ -375,7 +375,7 @@ void QmlProfilerApplication::traceFinished() { const QString fileName = traceFileName(); - if (m_profileData.save(fileName)) + if (m_profilerData.save(fileName)) print(QString("Saving trace to %1.").arg(fileName)); if (m_quitAfterSave) @@ -416,7 +416,7 @@ void QmlProfilerApplication::qmlComplete() m_qmlDataReady = true; if (m_v8profilerClient.state() != QQmlDebugClient::Enabled || m_v8DataReady) { - m_profileData.complete(); + m_profilerData.complete(); // once complete is sent, reset the flag m_qmlDataReady = false; } @@ -427,7 +427,7 @@ void QmlProfilerApplication::v8Complete() m_v8DataReady = true; if (m_qmlProfilerClient.state() != QQmlDebugClient::Enabled || m_qmlDataReady) { - m_profileData.complete(); + m_profilerData.complete(); // once complete is sent, reset the flag m_v8DataReady = false; } diff --git a/tools/qmlprofiler/qmlprofilerapplication.h b/tools/qmlprofiler/qmlprofilerapplication.h index 3937db7e5f..c7148880ad 100644 --- a/tools/qmlprofiler/qmlprofilerapplication.h +++ b/tools/qmlprofiler/qmlprofilerapplication.h @@ -46,7 +46,8 @@ #include #include -#include "profileclient.h" +#include "qmlprofilerclient.h" +#include "qmlprofilerdata.h" class QmlProfilerApplication : public QCoreApplication { @@ -104,9 +105,9 @@ private: bool m_quitAfterSave; QQmlDebugConnection m_connection; - QmlProfileClient m_qmlProfilerClient; - V8ProfileClient m_v8profilerClient; - ProfileData m_profileData; + QmlProfilerClient m_qmlProfilerClient; + V8ProfilerClient m_v8profilerClient; + QmlProfilerData m_profilerData; QTimer m_connectTimer; uint m_connectionAttempts; diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp new file mode 100644 index 0000000000..97ed90e890 --- /dev/null +++ b/tools/qmlprofiler/qmlprofilerclient.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlprofilerclient.h" + +#include +#include + +ProfilerClient::ProfilerClient(const QString &clientName, + QQmlDebugConnection *client) + : QQmlDebugClient(clientName, client), + m_recording(false), + m_enabled(false) +{ +} + +ProfilerClient::~ProfilerClient() +{ + //Disable profiling if started by client + //Profiling data will be lost!! + if (isRecording()) + setRecording(false); +} + +void ProfilerClient::clearData() +{ + emit cleared(); +} + +bool ProfilerClient::isEnabled() const +{ + return m_enabled; +} + +void ProfilerClient::sendRecordingStatus() +{ +} + +bool ProfilerClient::isRecording() const +{ + return m_recording; +} + +void ProfilerClient::setRecording(bool v) +{ + if (v == m_recording) + return; + + m_recording = v; + + if (state() == Enabled) { + sendRecordingStatus(); + } + + emit recordingChanged(v); +} + +void ProfilerClient::stateChanged(State status) +{ + if ((m_enabled && status != Enabled) || + (!m_enabled && status == Enabled)) + emit enabledChanged(); + + m_enabled = status == Enabled; + +} + +class QmlProfilerClientPrivate +{ +public: + QmlProfilerClientPrivate() + : inProgressRanges(0) + , maximumTime(0) + { + ::memset(rangeCount, 0, + QQmlProfilerService::MaximumRangeType * sizeof(int)); + } + + qint64 inProgressRanges; + QStack rangeStartTimes[QQmlProfilerService::MaximumRangeType]; + QStack rangeDatas[QQmlProfilerService::MaximumRangeType]; + QStack rangeLocations[QQmlProfilerService::MaximumRangeType]; + int rangeCount[QQmlProfilerService::MaximumRangeType]; + qint64 maximumTime; +}; + +QmlProfilerClient::QmlProfilerClient( + QQmlDebugConnection *client) + : ProfilerClient(QStringLiteral("CanvasFrameRate"), client), + d(new QmlProfilerClientPrivate) +{ +} + +QmlProfilerClient::~QmlProfilerClient() +{ + delete d; +} + +void QmlProfilerClient::clearData() +{ + ::memset(d->rangeCount, 0, + QQmlProfilerService::MaximumRangeType * sizeof(int)); + ProfilerClient::clearData(); +} + +void QmlProfilerClient::sendRecordingStatus() +{ + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + stream << isRecording(); + sendMessage(ba); +} + +void QmlProfilerClient::messageReceived(const QByteArray &data) +{ + QByteArray rwData = data; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + qint64 time; + int messageType; + + stream >> time >> messageType; + + if (messageType >= QQmlProfilerService::MaximumMessage) + return; + + if (messageType == QQmlProfilerService::Event) { + int event; + stream >> event; + + if (event == QQmlProfilerService::EndTrace) { + emit this->traceFinished(time); + d->maximumTime = time; + d->maximumTime = qMax(time, d->maximumTime); + } else if (event == QQmlProfilerService::AnimationFrame) { + int frameRate, animationCount; + stream >> frameRate >> animationCount; + emit this->frame(time, frameRate, animationCount); + d->maximumTime = qMax(time, d->maximumTime); + } else if (event == QQmlProfilerService::StartTrace) { + emit this->traceStarted(time); + d->maximumTime = time; + } else if (event < QQmlProfilerService::MaximumEventType) { + d->maximumTime = qMax(time, d->maximumTime); + } + } else if (messageType == QQmlProfilerService::Complete) { + emit complete(); + + } else { + int range; + stream >> range; + + if (range >= QQmlProfilerService::MaximumRangeType) + return; + + if (messageType == QQmlProfilerService::RangeStart) { + d->rangeStartTimes[range].push(time); + d->inProgressRanges |= (static_cast(1) << range); + ++d->rangeCount[range]; + } else if (messageType == QQmlProfilerService::RangeData) { + QString data; + stream >> data; + + int count = d->rangeCount[range]; + if (count > 0) { + while (d->rangeDatas[range].count() < count) + d->rangeDatas[range].push(QStringList()); + d->rangeDatas[range][count-1] << data; + } + + } else if (messageType == QQmlProfilerService::RangeLocation) { + QString fileName; + int line; + int column = -1; + stream >> fileName >> line; + + if (!stream.atEnd()) + stream >> column; + + if (d->rangeCount[range] > 0) { + d->rangeLocations[range].push(QmlEventLocation(fileName, line, + column)); + } + } else { + if (d->rangeCount[range] > 0) { + --d->rangeCount[range]; + if (d->inProgressRanges & (static_cast(1) << range)) + d->inProgressRanges &= ~(static_cast(1) << range); + + d->maximumTime = qMax(time, d->maximumTime); + QStringList data = d->rangeDatas[range].count() ? + d->rangeDatas[range].pop() : QStringList(); + QmlEventLocation location = d->rangeLocations[range].count() ? + d->rangeLocations[range].pop() : QmlEventLocation(); + + qint64 startTime = d->rangeStartTimes[range].pop(); + emit this->range((QQmlProfilerService::RangeType)range, + startTime, time - startTime, data, location); + if (d->rangeCount[range] == 0) { + int count = d->rangeDatas[range].count() + + d->rangeStartTimes[range].count() + + d->rangeLocations[range].count(); + if (count != 0) + qWarning() << "incorrectly nested data"; + } + } + } + } +} + +V8ProfilerClient::V8ProfilerClient(QQmlDebugConnection *client) + : ProfilerClient(QStringLiteral("V8Profiler"), client) +{ +} + +V8ProfilerClient::~V8ProfilerClient() +{ +} + +void V8ProfilerClient::sendRecordingStatus() +{ + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + QByteArray cmd("V8PROFILER"); + QByteArray option(""); + QByteArray title(""); + + if (m_recording) { + option = "start"; + } else { + option = "stop"; + } + stream << cmd << option << title; + sendMessage(ba); +} + +void V8ProfilerClient::messageReceived(const QByteArray &data) +{ + QByteArray rwData = data; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + int messageType; + + stream >> messageType; + + if (messageType == V8Complete) { + emit complete(); + } else if (messageType == V8Entry) { + QString filename; + QString function; + int lineNumber; + double totalTime; + double selfTime; + int depth; + + stream >> filename >> function >> lineNumber >> totalTime >> + selfTime >> depth; + emit this->range(depth, function, filename, lineNumber, totalTime, + selfTime); + } +} + diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h new file mode 100644 index 0000000000..2a8629d1fb --- /dev/null +++ b/tools/qmlprofiler/qmlprofilerclient.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROFILERCLIENT_H +#define QMLPROFILERCLIENT_H + +#include "qqmldebugclient.h" +#include +#include "qmlprofilereventlocation.h" + +class ProfilerClientPrivate; +class ProfilerClient : public QQmlDebugClient +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool recording READ isRecording WRITE setRecording + NOTIFY recordingChanged) + +public: + ProfilerClient(const QString &clientName, + QQmlDebugConnection *client); + ~ProfilerClient(); + + bool isEnabled() const; + bool isRecording() const; + +public slots: + void setRecording(bool); + virtual void clearData(); + virtual void sendRecordingStatus(); + +signals: + void complete(); + void recordingChanged(bool arg); + void enabledChanged(); + void cleared(); + +protected: + virtual void stateChanged(State); + +protected: + bool m_recording; + bool m_enabled; +}; + +class QmlProfilerClient : public ProfilerClient +{ + Q_OBJECT + +public: + QmlProfilerClient(QQmlDebugConnection *client); + ~QmlProfilerClient(); + +public slots: + void clearData(); + void sendRecordingStatus(); + +signals: + void traceFinished( qint64 time ); + void traceStarted( qint64 time ); + void range(QQmlProfilerService::RangeType type, qint64 startTime, + qint64 length, const QStringList &data, + const QmlEventLocation &location); + void frame(qint64 time, int frameRate, int animationCount); + +protected: + virtual void messageReceived(const QByteArray &); + +private: + class QmlProfilerClientPrivate *d; +}; + +class V8ProfilerClient : public ProfilerClient +{ + Q_OBJECT + +public: + enum Message { + V8Entry, + V8Complete, + + V8MaximumMessage + }; + + V8ProfilerClient(QQmlDebugConnection *client); + ~V8ProfilerClient(); + +public slots: + void sendRecordingStatus(); + +signals: + void range(int depth, const QString &function, const QString &filename, + int lineNumber, double totalTime, double selfTime); + +protected: + virtual void messageReceived(const QByteArray &); +}; + +#endif // QMLPROFILERCLIENT_H diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp new file mode 100644 index 0000000000..38e64ff46e --- /dev/null +++ b/tools/qmlprofiler/qmlprofilerdata.cpp @@ -0,0 +1,602 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlprofilerdata.h" + +#include +#include +#include +#include +#include + +namespace Constants { + const char TYPE_PAINTING_STR[] = "Painting"; + const char TYPE_COMPILING_STR[] = "Compiling"; + const char TYPE_CREATING_STR[] = "Creating"; + const char TYPE_BINDING_STR[] = "Binding"; + const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; + const char PROFILER_FILE_VERSION[] = "1.02"; +} + +struct QmlRangeEventData { + QmlRangeEventData() {} // never called + QmlRangeEventData(const QString &_displayName, + const QString &_eventHashStr, + const QmlEventLocation &_location, + const QString &_details, + const QQmlProfilerService::RangeType &_eventType) + : displayName(_displayName),eventHashStr(_eventHashStr),location(_location), + details(_details),eventType(_eventType) {} + QString displayName; + QString eventHashStr; + QmlEventLocation location; + QString details; + QQmlProfilerService::RangeType eventType; +}; + +struct QmlRangeEventStartInstance { + QmlRangeEventStartInstance() {} // never called + QmlRangeEventStartInstance(qint64 _startTime, qint64 _duration, int _frameRate, + int _animationCount, QmlRangeEventData *_data) + : startTime(_startTime), duration(_duration), frameRate(_frameRate), + animationCount(_animationCount), data(_data) + { } + qint64 startTime; + qint64 duration; + int frameRate; + int animationCount; + QmlRangeEventData *data; +}; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QmlRangeEventData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlRangeEventStartInstance, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +struct QV8EventInfo { + QString displayName; + QString eventHashStr; + QString functionName; + QString fileName; + int line; + qint64 totalTime; + qint64 selfTime; + + QHash v8children; +}; + +///////////////////////////////////////////////////////////////// +class QmlProfilerDataPrivate +{ +public: + QmlProfilerDataPrivate(QmlProfilerData *qq){ Q_UNUSED(qq); } + + // data storage + QHash eventDescriptions; + QVector startInstanceList; + QHash v8EventHash; + + qint64 traceStartTime; + qint64 traceEndTime; + + // internal state while collecting events + QmlRangeEventStartInstance *lastFrameEvent; + qint64 qmlMeasuredTime; + qint64 v8MeasuredTime; + QHash v8parents; + void clearV8RootEvent(); + QV8EventInfo v8RootEvent; + + QmlProfilerData::State state; +}; + +///////////////////////////////////////////////////////////////// +QmlProfilerData::QmlProfilerData(QObject *parent) : + QObject(parent),d(new QmlProfilerDataPrivate(this)) +{ + d->state = Empty; + clear(); +} + +QmlProfilerData::~QmlProfilerData() +{ + clear(); + delete d; +} + +void QmlProfilerData::clear() +{ + qDeleteAll(d->eventDescriptions.values()); + d->eventDescriptions.clear(); + d->startInstanceList.clear(); + + qDeleteAll(d->v8EventHash.values()); + d->v8EventHash.clear(); + d->v8parents.clear(); + d->clearV8RootEvent(); + d->v8MeasuredTime = 0; + + d->traceEndTime = 0; + d->traceStartTime = -1; + d->qmlMeasuredTime = 0; + + d->lastFrameEvent = 0; + + setState(Empty); +} + +QString QmlProfilerData::getHashStringForQmlEvent(const QmlEventLocation &location, int eventType) +{ + return QString(QStringLiteral("%1:%2:%3:%4")).arg( + location.filename, + QString::number(location.line), + QString::number(location.column), + QString::number(eventType)); +} + +QString QmlProfilerData::getHashStringForV8Event(const QString &displayName, const QString &function) +{ + return QString(QStringLiteral("%1:%2")).arg(displayName, function); +} + +QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerService::RangeType typeEnum) +{ + switch (typeEnum) { + case QQmlProfilerService::Painting: + return QLatin1String(Constants::TYPE_PAINTING_STR); + break; + case QQmlProfilerService::Compiling: + return QLatin1String(Constants::TYPE_COMPILING_STR); + break; + case QQmlProfilerService::Creating: + return QLatin1String(Constants::TYPE_CREATING_STR); + break; + case QQmlProfilerService::Binding: + return QLatin1String(Constants::TYPE_BINDING_STR); + break; + case QQmlProfilerService::HandlingSignal: + return QLatin1String(Constants::TYPE_HANDLINGSIGNAL_STR); + break; + default: + return QString::number((int)typeEnum); + } +} + +void QmlProfilerData::setTraceStartTime(qint64 time) +{ + d->traceStartTime = time; +} + +void QmlProfilerData::setTraceEndTime(qint64 time) +{ + d->traceEndTime = time; +} + +qint64 QmlProfilerData::traceStartTime() const +{ + return d->traceStartTime; +} + +qint64 QmlProfilerData::traceEndTime() const +{ + return d->traceEndTime; +} + +void QmlProfilerData::addQmlEvent(QQmlProfilerService::RangeType type, + qint64 startTime, + qint64 duration, + const QStringList &data, + const QmlEventLocation &location) +{ + setState(AcquiringData); + + QString details; + // generate details string + if (data.isEmpty()) + details = tr("Source code not available"); + else { + details = data.join(QStringLiteral(" ")).replace( + QLatin1Char('\n'),QStringLiteral(" ")).simplified(); + QRegExp rewrite(QStringLiteral("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)")); + bool match = rewrite.exactMatch(details); + if (match) { + details = rewrite.cap(1) +QLatin1String(": ") + rewrite.cap(3); + } + if (details.startsWith(QLatin1String("file://"))) + details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1); + } + + QmlEventLocation eventLocation = location; + QString displayName, eventHashStr; + // generate hash + if (eventLocation.filename.isEmpty()) { + displayName = tr(""); + eventHashStr = getHashStringForQmlEvent(eventLocation, type); + } else { + const QString filePath = QUrl(eventLocation.filename).path(); + displayName = filePath.mid( + filePath.lastIndexOf(QLatin1Char('/')) + 1) + + QLatin1Char(':') + QString::number(eventLocation.line); + eventHashStr = getHashStringForQmlEvent(eventLocation, type); + } + + QmlRangeEventData *newEvent; + if (d->eventDescriptions.contains(eventHashStr)) { + newEvent = d->eventDescriptions[eventHashStr]; + } else { + newEvent = new QmlRangeEventData(displayName, eventHashStr, location, details, type); + d->eventDescriptions.insert(eventHashStr, newEvent); + } + + QmlRangeEventStartInstance rangeEventStartInstance(startTime, duration, 1e9/duration, -1, newEvent); + + d->startInstanceList.append(rangeEventStartInstance); +} + +void QmlProfilerData::addFrameEvent(qint64 time, int framerate, int animationcount) +{ + setState(AcquiringData); + + QString details = tr("Animation Timer Update"); + QString displayName = tr(""); + QString eventHashStr = displayName; + + QmlRangeEventData *newEvent; + if (d->eventDescriptions.contains(eventHashStr)) { + newEvent = d->eventDescriptions[eventHashStr]; + } else { + newEvent = new QmlRangeEventData(displayName, eventHashStr, QmlEventLocation(), details, QQmlProfilerService::Painting); + d->eventDescriptions.insert(eventHashStr, newEvent); + } + + qint64 duration = 1e9/framerate; + // avoid overlap + if (d->lastFrameEvent && + d->lastFrameEvent->startTime + d->lastFrameEvent->duration >= time) { + d->lastFrameEvent->duration = time - 1 - d->lastFrameEvent->startTime; + } + + QmlRangeEventStartInstance rangeEventStartInstance(time, duration, framerate, animationcount, newEvent); + + d->startInstanceList.append(rangeEventStartInstance); + + d->lastFrameEvent = &d->startInstanceList.last(); +} + +QString QmlProfilerData::rootEventName() +{ + return tr(""); +} + +QString QmlProfilerData::rootEventDescription() +{ + return tr("Main Program"); +} + +void QmlProfilerDataPrivate::clearV8RootEvent() +{ + v8RootEvent.displayName = QmlProfilerData::rootEventName(); + v8RootEvent.eventHashStr = QmlProfilerData::rootEventName(); + v8RootEvent.functionName = QmlProfilerData::rootEventDescription(); + v8RootEvent.line = -1; + v8RootEvent.totalTime = 0; + v8RootEvent.selfTime = 0; + v8RootEvent.v8children.clear(); +} + +void QmlProfilerData::addV8Event(int depth, const QString &function, const QString &filename, + int lineNumber, double totalTime, double selfTime) +{ + QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + + QLatin1Char(':') + QString::number(lineNumber); + QString hashStr = getHashStringForV8Event(displayName, function); + + setState(AcquiringData); + + // time is given in milliseconds, but internally we store it in microseconds + totalTime *= 1e6; + selfTime *= 1e6; + + // accumulate information + QV8EventInfo *eventData = d->v8EventHash[hashStr]; + if (!eventData) { + eventData = new QV8EventInfo; + eventData->displayName = displayName; + eventData->eventHashStr = hashStr; + eventData->fileName = filename; + eventData->functionName = function; + eventData->line = lineNumber; + eventData->totalTime = totalTime; + eventData->selfTime = selfTime; + d->v8EventHash[hashStr] = eventData; + } else { + eventData->totalTime += totalTime; + eventData->selfTime += selfTime; + } + d->v8parents[depth] = eventData; + + QV8EventInfo *parentEvent = 0; + if (depth == 0) { + parentEvent = &d->v8RootEvent; + d->v8MeasuredTime += totalTime; + } + if (depth > 0 && d->v8parents.contains(depth-1)) { + parentEvent = d->v8parents.value(depth-1); + } + + if (parentEvent != 0) { + if (!parentEvent->v8children.contains(eventData->eventHashStr)) { + parentEvent->v8children[eventData->eventHashStr] = totalTime; + } else { + parentEvent->v8children[eventData->eventHashStr] += totalTime; + } + } +} + +void QmlProfilerData::computeQmlTime() +{ + // compute levels + QHash endtimesPerLevel; + int minimumLevel = 1; + int level = minimumLevel; + + for (int i = 0; i < d->startInstanceList.count(); i++) { + qint64 st = d->startInstanceList[i].startTime; + int type = d->startInstanceList[i].data->eventType; + + if (type == QQmlProfilerService::Painting) { + continue; + } + + // general level + if (endtimesPerLevel[level] > st) { + level++; + } else { + while (level > minimumLevel && endtimesPerLevel[level-1] <= st) + level--; + } + endtimesPerLevel[level] = st + d->startInstanceList[i].duration; + + if (level == minimumLevel) { + d->qmlMeasuredTime += d->startInstanceList[i].duration; + } + } +} + +bool compareStartTimes(const QmlRangeEventStartInstance &t1, const QmlRangeEventStartInstance &t2) +{ + return t1.startTime < t2.startTime; +} + +void QmlProfilerData::sortStartTimes() +{ + if (d->startInstanceList.count() < 2) + return; + + // assuming startTimes is partially sorted + // identify blocks of events and sort them with quicksort + QVector::iterator itFrom = d->startInstanceList.end() - 2; + QVector::iterator itTo = d->startInstanceList.end() - 1; + + while (itFrom != d->startInstanceList.begin() && itTo != d->startInstanceList.begin()) { + // find block to sort + while ( itFrom != d->startInstanceList.begin() + && itTo->startTime > itFrom->startTime ) { + itTo--; + itFrom = itTo - 1; + } + + // if we're at the end of the list + if (itFrom == d->startInstanceList.begin()) + break; + + // find block length + while ( itFrom != d->startInstanceList.begin() + && itTo->startTime <= itFrom->startTime ) + itFrom--; + + if (itTo->startTime <= itFrom->startTime) + qSort(itFrom, itTo + 1, compareStartTimes); + else + qSort(itFrom + 1, itTo + 1, compareStartTimes); + + // move to next block + itTo = itFrom; + itFrom = itTo - 1; + } +} + +void QmlProfilerData::complete() +{ + setState(ProcessingData); + sortStartTimes(); + computeQmlTime(); + setState(Done); + emit dataReady(); +} + +bool QmlProfilerData::isEmpty() const +{ + return d->startInstanceList.isEmpty() && d->v8EventHash.isEmpty(); +} + +bool QmlProfilerData::save(const QString &filename) +{ + if (isEmpty()) { + emit error(tr("No data to save")); + return false; + } + + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + emit error(tr("Could not open %1 for writing").arg(filename)); + return false; + } + + QXmlStreamWriter stream(&file); + stream.setAutoFormatting(true); + stream.writeStartDocument(); + + stream.writeStartElement(QStringLiteral("trace")); + stream.writeAttribute(QStringLiteral("version"), QLatin1String(Constants::PROFILER_FILE_VERSION)); + + stream.writeAttribute(QStringLiteral("traceStart"), QString::number(traceStartTime())); + stream.writeAttribute(QStringLiteral("traceEnd"), QString::number(traceEndTime())); + + stream.writeStartElement(QStringLiteral("eventData")); + stream.writeAttribute(QStringLiteral("totalTime"), QString::number(d->qmlMeasuredTime)); + + foreach (const QmlRangeEventData *eventData, d->eventDescriptions.values()) { + stream.writeStartElement(QStringLiteral("event")); + stream.writeAttribute(QStringLiteral("index"), QString::number(d->eventDescriptions.keys().indexOf(eventData->eventHashStr))); + stream.writeTextElement(QStringLiteral("displayname"), eventData->displayName); + stream.writeTextElement(QStringLiteral("type"), qmlRangeTypeAsString(eventData->eventType)); + if (!eventData->location.filename.isEmpty()) { + stream.writeTextElement(QStringLiteral("filename"), eventData->location.filename); + stream.writeTextElement(QStringLiteral("line"), QString::number(eventData->location.line)); + stream.writeTextElement(QStringLiteral("column"), QString::number(eventData->location.column)); + } + stream.writeTextElement(QStringLiteral("details"), eventData->details); + stream.writeEndElement(); + } + stream.writeEndElement(); // eventData + + stream.writeStartElement(QStringLiteral("profilerDataModel")); + foreach (const QmlRangeEventStartInstance &rangedEvent, d->startInstanceList) { + stream.writeStartElement(QStringLiteral("range")); + stream.writeAttribute(QStringLiteral("startTime"), QString::number(rangedEvent.startTime)); + stream.writeAttribute(QStringLiteral("duration"), QString::number(rangedEvent.duration)); + stream.writeAttribute(QStringLiteral("eventIndex"), QString::number(d->eventDescriptions.keys().indexOf(rangedEvent.data->eventHashStr))); + if (rangedEvent.data->eventType == QQmlProfilerService::Painting && rangedEvent.animationCount >= 0) { + // animation frame + stream.writeAttribute(QStringLiteral("framerate"), QString::number(rangedEvent.frameRate)); + stream.writeAttribute(QStringLiteral("animationcount"), QString::number(rangedEvent.animationCount)); + } + stream.writeEndElement(); + } + stream.writeEndElement(); // profilerDataModel + + stream.writeStartElement(QStringLiteral("v8profile")); // v8 profiler output + stream.writeAttribute(QStringLiteral("totalTime"), QString::number(d->v8MeasuredTime)); + foreach (QV8EventInfo *v8event, d->v8EventHash.values()) { + stream.writeStartElement(QStringLiteral("event")); + stream.writeAttribute(QStringLiteral("index"), QString::number(d->v8EventHash.keys().indexOf(v8event->eventHashStr))); + stream.writeTextElement(QStringLiteral("displayname"), v8event->displayName); + stream.writeTextElement(QStringLiteral("functionname"), v8event->functionName); + if (!v8event->fileName.isEmpty()) { + stream.writeTextElement(QStringLiteral("filename"), v8event->fileName); + stream.writeTextElement(QStringLiteral("line"), QString::number(v8event->line)); + } + stream.writeTextElement(QStringLiteral("totalTime"), QString::number(v8event->totalTime)); + stream.writeTextElement(QStringLiteral("selfTime"), QString::number(v8event->selfTime)); + if (!v8event->v8children.isEmpty()) { + stream.writeStartElement(QStringLiteral("childrenEvents")); + QStringList childrenIndexes; + QStringList childrenTimes; + foreach (const QString &childHash, v8event->v8children.keys()) { + childrenIndexes << QString::number(v8EventIndex(childHash)); + childrenTimes << QString::number(v8event->v8children[childHash]); + } + + stream.writeAttribute(QStringLiteral("list"), childrenIndexes.join(QString(", "))); + stream.writeAttribute(QStringLiteral("childrenTimes"), childrenTimes.join(QString(", "))); + stream.writeEndElement(); + } + stream.writeEndElement(); + } + stream.writeEndElement(); // v8 profiler output + + stream.writeEndElement(); // trace + stream.writeEndDocument(); + + file.close(); + return true; +} + +int QmlProfilerData::v8EventIndex(const QString &hashStr) +{ + if (!d->v8EventHash.contains(hashStr)) { + emit error("Trying to index nonexisting v8 event"); + return -1; + } + return d->v8EventHash.keys().indexOf( hashStr ); +} + +void QmlProfilerData::setState(QmlProfilerData::State state) +{ + // It's not an error, we are continuously calling "AcquiringData" for example + if (d->state == state) + return; + + switch (state) { + case Empty: + // if it's not empty, complain but go on + if (!isEmpty()) + emit error("Invalid qmlprofiler state change (Empty)"); + break; + case AcquiringData: + // we're not supposed to receive new data while processing older data + if (d->state == ProcessingData) + emit error("Invalid qmlprofiler state change (AcquiringData)"); + break; + case ProcessingData: + if (d->state != AcquiringData) + emit error("Invalid qmlprofiler state change (ProcessingData)"); + break; + case Done: + if (d->state != ProcessingData && d->state != Empty) + emit error("Invalid qmlprofiler state change (Done)"); + break; + default: + emit error("Trying to set unknown state in events list"); + break; + } + + d->state = state; + emit stateChanged(); + + // special: if we were done with an empty list, clean internal data and go back to empty + if (d->state == Done && isEmpty()) { + clear(); + } + return; +} + diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h new file mode 100644 index 0000000000..66209a1830 --- /dev/null +++ b/tools/qmlprofiler/qmlprofilerdata.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROFILERDATA_H +#define QMLPROFILERDATA_H + +#include +#include "qmlprofilereventlocation.h" + +#include + +class QmlProfilerDataPrivate; +class QmlProfilerData : public QObject +{ + Q_OBJECT +public: + enum State { + Empty, + AcquiringData, + ProcessingData, + Done + }; + + explicit QmlProfilerData(QObject *parent = 0); + ~QmlProfilerData(); + + static QString getHashStringForQmlEvent(const QmlEventLocation &location, int eventType); + static QString getHashStringForV8Event(const QString &displayName, const QString &function); + static QString qmlRangeTypeAsString(QQmlProfilerService::RangeType typeEnum); + static QString rootEventName(); + static QString rootEventDescription(); + + qint64 traceStartTime() const; + qint64 traceEndTime() const; + + bool isEmpty() const; + +signals: + void error(QString); + void stateChanged(); + void dataReady(); + +public slots: + void clear(); + void setTraceEndTime(qint64 time); + void setTraceStartTime(qint64 time); + void addQmlEvent(QQmlProfilerService::RangeType type, qint64 startTime, qint64 duration, + const QStringList &data, const QmlEventLocation &location); + void addV8Event(int depth, const QString &function, const QString &filename, + int lineNumber, double totalTime, double selfTime); + void addFrameEvent(qint64 time, int framerate, int animationcount); + + void complete(); + bool save(const QString &filename); + +private: + void sortStartTimes(); + int v8EventIndex(const QString &hashStr); + void computeQmlTime(); + void setState(QmlProfilerData::State state); + +private: + QmlProfilerDataPrivate *d; +}; + +#endif // QMLPROFILERDATA_H diff --git a/tools/qmlprofiler/qmlprofilereventlocation.h b/tools/qmlprofiler/qmlprofilereventlocation.h new file mode 100644 index 0000000000..a34b6aba6d --- /dev/null +++ b/tools/qmlprofiler/qmlprofilereventlocation.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTLOCATION_H +#define QMLPROFILEREVENTLOCATION_H + +#include + +struct QmlEventLocation +{ + QmlEventLocation() : line(-1), column(-1) {} + QmlEventLocation(const QString &file, int lineNumber, int columnNumber) + : filename(file), line(lineNumber), column(columnNumber) {} + QString filename; + int line; + int column; +}; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QmlEventLocation, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +#endif // QMLPROFILEREVENTLOCATION_H -- cgit v1.2.3 From 70ac6b1705b0c500c136129bc9691050a50b442a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 13 Mar 2012 15:54:19 +1000 Subject: Reuse QQuickView in ListView table driven tests Makes the tests run faster since we're not waiting for a window to appear all the time. Change-Id: Ibff3706873dbad2f92d2135eae260368f4f4bb10 Reviewed-by: Bea Lam --- .../quick/qquicklistview/tst_qquicklistview.cpp | 133 ++++++++++++++------- 1 file changed, 89 insertions(+), 44 deletions(-) diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 1a494183a8..14707cab1d 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -63,6 +63,8 @@ Q_DECLARE_METATYPE(QQuickListView::Orientation) using namespace QQuickViewTestUtil; using namespace QQuickVisualTestUtil; +#define SHARE_VIEWS + class tst_QQuickListView : public QQmlDataTest { Q_OBJECT @@ -70,6 +72,7 @@ public: tst_QQuickListView(); private slots: + void init(); // Test both QListModelInterface and QAbstractItemModel model types void qListModelInterface_items(); void qListModelInterface_package_items(); @@ -206,6 +209,38 @@ private: void inserted_more_data(); void removed_more_data(); void moved_data(); + +#ifdef SHARE_VIEWS + QQuickView *getView() { + if (m_view) { + if (QString(QTest::currentTestFunction()) != testForView) { + delete m_view; + m_view = 0; + } else { + m_view->setSource(QUrl()); + return m_view; + } + } + + testForView = QTest::currentTestFunction(); + m_view = createView(); + return m_view; + } + void releaseView(QQuickView *view) { + Q_ASSERT(view == m_view); + m_view->setSource(QUrl()); + } +#else + QQuickView *getView() { + return createView(); + } + void releaseView(QQuickView *view) { + delete view; + } +#endif + + QQuickView *m_view; + QString testForView; }; class TestObject : public QObject @@ -247,10 +282,21 @@ public: int mCacheBuffer; }; -tst_QQuickListView::tst_QQuickListView() +tst_QQuickListView::tst_QQuickListView() : m_view(0) { } +void tst_QQuickListView::init() +{ +#ifdef SHARE_VIEWS + if (m_view && QString(QTest::currentTestFunction()) != testForView) { + testForView = QString(); + delete m_view; + m_view = 0; + } +#endif +} + template void tst_QQuickListView::items(const QUrl &source, bool forceLayout) { @@ -486,7 +532,7 @@ void tst_QQuickListView::inserted_more() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); @@ -544,7 +590,7 @@ void tst_QQuickListView::inserted_more() QTRY_COMPARE(number->text(), model.number(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -635,7 +681,7 @@ void tst_QQuickListView::insertBeforeVisible() QFETCH(int, cacheBuffer); QQuickText *name; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QmlListModel model; for (int i = 0; i < 30; i++) @@ -696,7 +742,7 @@ void tst_QQuickListView::insertBeforeVisible() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -914,7 +960,7 @@ void tst_QQuickListView::removed_more(const QUrl &source) QQuickText *name; QQuickText *number; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); T model; for (int i = 0; i < 30; i++) @@ -976,7 +1022,7 @@ void tst_QQuickListView::removed_more(const QUrl &source) QTRY_COMPARE(number->text(), model.number(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -1136,7 +1182,7 @@ void tst_QQuickListView::moved(const QUrl &source) QQuickText *name; QQuickText *number; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); T model; for (int i = 0; i < 30; i++) @@ -1201,7 +1247,7 @@ void tst_QQuickListView::moved(const QUrl &source) QTRY_COMPARE(listview->currentIndex(), i); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -1363,7 +1409,7 @@ void tst_QQuickListView::multipleChanges() QFETCH(int, newCount); QFETCH(int, newCurrentIndex); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QmlListModel model; for (int i = 0; i < startCount; i++) @@ -1435,7 +1481,7 @@ void tst_QQuickListView::multipleChanges() } delete testObject; - delete canvas; + releaseView(canvas); } void tst_QQuickListView::multipleChanges_data() @@ -2189,7 +2235,7 @@ void tst_QQuickListView::currentIndex_delayedItemCreation() { QFETCH(bool, setCurrentToZero); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); // test currentIndexChanged() is emitted even if currentIndex = 0 on start up // (since the currentItem will have changed and that shares the same index) @@ -2207,7 +2253,7 @@ void tst_QQuickListView::currentIndex_delayedItemCreation() QCOMPARE(listview->currentIndex(), 0); QTRY_COMPARE(spy.count(), 1); - delete canvas; + releaseView(canvas); } void tst_QQuickListView::currentIndex_delayedItemCreation_data() @@ -3030,7 +3076,7 @@ void tst_QQuickListView::header() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("initialViewWidth", 240); canvas->rootContext()->setContextProperty("initialViewHeight", 320); @@ -3092,12 +3138,12 @@ void tst_QQuickListView::header() QVERIFY(item); QCOMPARE(item->pos(), firstDelegatePos); - delete canvas; + releaseView(canvas); // QTBUG-21207 header should become visible if view resizes from initial empty size - canvas = createView(); + canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("initialViewWidth", 0.0); canvas->rootContext()->setContextProperty("initialViewHeight", 0.0); @@ -3116,8 +3162,7 @@ void tst_QQuickListView::header() QTRY_COMPARE(listview->headerItem()->pos(), initialHeaderPos); QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos); - - delete canvas; + releaseView(canvas); } void tst_QQuickListView::header_data() @@ -3212,7 +3257,7 @@ void tst_QQuickListView::footer() QFETCH(QPointF, changedContentPos); QFETCH(QPointF, resizeContentPos); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QmlListModel model; for (int i = 0; i < 3; i++) @@ -3306,7 +3351,7 @@ void tst_QQuickListView::footer() footer->setWidth(40); QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos); - delete canvas; + releaseView(canvas); } void tst_QQuickListView::footer_data() @@ -3835,7 +3880,7 @@ void tst_QQuickListView::indexAt_itemAt() QFETCH(qreal, y); QFETCH(int, index); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QmlListModel model; for (int i = 0; i < 30; i++) @@ -3866,7 +3911,7 @@ void tst_QQuickListView::indexAt_itemAt() QCOMPARE(listview->indexAt(x,y), index); QVERIFY(listview->itemAt(x,y) == item); - delete canvas; + releaseView(canvas); delete testObject; } @@ -3963,7 +4008,7 @@ void tst_QQuickListView::onRemove() for (int i=0; irootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("delegateHeight", delegateHeight); @@ -3976,7 +4021,7 @@ void tst_QQuickListView::onRemove() QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); - delete canvas; + releaseView(canvas); } void tst_QQuickListView::onRemove_data() @@ -4189,7 +4234,7 @@ void tst_QQuickListView::marginsResize() QFETCH(qreal, start); QFETCH(qreal, end); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("margins2.qml")); canvas->show(); @@ -4222,7 +4267,7 @@ void tst_QQuickListView::marginsResize() else QTRY_COMPARE(listview->contentX(), start); - delete canvas; + releaseView(canvas); } void tst_QQuickListView::marginsResize_data() @@ -4278,7 +4323,7 @@ void tst_QQuickListView::snapToItem() QFETCH(qreal, endExtent); QFETCH(qreal, startExtent); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("snapToItem.qml")); canvas->show(); @@ -4329,7 +4374,7 @@ void tst_QQuickListView::snapToItem() else QCOMPARE(listview->contentX(), startExtent); - delete canvas; + releaseView(canvas); } void tst_QQuickListView::qListModelInterface_items() @@ -4620,7 +4665,7 @@ void tst_QQuickListView::snapOneItem() QSKIP("QTBUG-24338"); #endif - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("snapOneItem.qml")); canvas->show(); @@ -4688,7 +4733,7 @@ void tst_QQuickListView::snapOneItem() QCOMPARE(currentIndexSpy.count(), 6); } - delete canvas; + releaseView(canvas); } void tst_QQuickListView::unrequestedVisibility() @@ -4873,7 +4918,7 @@ void tst_QQuickListView::populateTransitions() model.addItem("item" + QString::number(i), ""); } - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("testObject", new TestObject(canvas->rootContext())); canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition); @@ -4971,7 +5016,7 @@ void tst_QQuickListView::populateTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickListView::populateTransitions_data() @@ -5011,7 +5056,7 @@ void tst_QQuickListView::addTransitions() QaimModel model_targetItems_transitionFrom; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); TestObject *testObject = new TestObject; ctxt->setContextProperty("testModel", &model); @@ -5109,7 +5154,7 @@ void tst_QQuickListView::addTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -5206,7 +5251,7 @@ void tst_QQuickListView::moveTransitions() QaimModel model_targetItems_transitionVia; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); TestObject *testObject = new TestObject; ctxt->setContextProperty("testModel", &model); @@ -5294,7 +5339,7 @@ void tst_QQuickListView::moveTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -5409,7 +5454,7 @@ void tst_QQuickListView::removeTransitions() QaimModel model_targetItems_transitionTo; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); TestObject *testObject = new TestObject; ctxt->setContextProperty("testModel", &model); @@ -5508,7 +5553,7 @@ void tst_QQuickListView::removeTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -5608,7 +5653,7 @@ void tst_QQuickListView::displacedTransitions() QPointF moveDisplaced_transitionVia(50, -100); QPointF removeDisplaced_transitionVia(150, 100); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); TestObject *testObject = new TestObject(canvas); ctxt->setContextProperty("testModel", &model); @@ -5720,7 +5765,7 @@ void tst_QQuickListView::displacedTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickListView::displacedTransitions_data() @@ -5832,7 +5877,7 @@ void tst_QQuickListView::multipleTransitions() for (int i = 0; i < initialCount; i++) model.addItem("Original item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); TestObject *testObject = new TestObject; ctxt->setContextProperty("testModel", &model); @@ -5924,7 +5969,7 @@ void tst_QQuickListView::multipleTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); delete testObject; } @@ -5996,7 +6041,7 @@ void tst_QQuickListView::multipleDisplaced() for (int i = 0; i < 30; i++) model.addItem("Original item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("testObject", new TestObject(canvas)); @@ -6033,7 +6078,7 @@ void tst_QQuickListView::multipleDisplaced() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } QList tst_QQuickListView::toIntList(const QVariantList &list) -- cgit v1.2.3 From fd1e8c80f8f62d1d96f809ef292eb452491da98c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 8 Mar 2012 15:01:53 +0100 Subject: Debugger: Use QStringLiteral where appropriate Change-Id: I5c33113783834ef0c7292f5f19f12d8c68f42141 Reviewed-by: Aurindam Jana --- src/qml/debugger/qdebugmessageservice.cpp | 2 +- src/qml/debugger/qqmldebugserver.cpp | 24 ++++++++++++------------ src/qml/debugger/qqmldebugservice.cpp | 4 ++-- src/qml/debugger/qqmlenginedebugservice.cpp | 16 ++++++++-------- src/qml/debugger/qqmlinspectorservice.cpp | 2 +- src/qml/debugger/qqmlprofilerservice.cpp | 2 +- src/qml/debugger/qv8debugservice.cpp | 2 +- src/qml/debugger/qv8profilerservice.cpp | 2 +- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/qml/debugger/qdebugmessageservice.cpp b/src/qml/debugger/qdebugmessageservice.cpp index dcaa514cd7..a41f95c2c7 100644 --- a/src/qml/debugger/qdebugmessageservice.cpp +++ b/src/qml/debugger/qdebugmessageservice.cpp @@ -69,7 +69,7 @@ public: QDebugMessageService::QDebugMessageService(QObject *parent) : QQmlDebugService(*(new QDebugMessageServicePrivate()), - QLatin1String("DebugMessages"), 2, parent) + QStringLiteral("DebugMessages"), 2, parent) { Q_D(QDebugMessageService); diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp index e70632d925..23b69af92b 100644 --- a/src/qml/debugger/qqmldebugserver.cpp +++ b/src/qml/debugger/qqmldebugserver.cpp @@ -155,7 +155,7 @@ void QQmlDebugServerPrivate::advertisePlugins() pluginNames << service->name(); pluginVersions << service->version(); } - out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << pluginNames << pluginVersions; + out << QString(QStringLiteral("QDeclarativeDebugClient")) << 1 << pluginNames << pluginVersions; } QMetaObject::invokeMethod(q, "_q_sendMessages", Qt::QueuedConnection, Q_ARG(QList, QList() << message)); @@ -217,8 +217,8 @@ void QQmlDebugServerThread::run() connection->setPort(m_port, m_block); } else { QCoreApplicationPrivate *appD = static_cast(QObjectPrivate::get(qApp)); - qWarning() << QString::fromAscii("QML Debugger: Ignoring \"-qmljsdebugger=%1\". " - "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString()); + qWarning() << QString(QLatin1String("QML Debugger: Ignoring \"-qmljsdebugger=%1\". " + "Remote debugger plugin has not been found.")).arg(appD->qmljsDebugArgumentsString()); } exec(); @@ -262,9 +262,9 @@ QQmlDebugServer *QQmlDebugServer::instance() // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block] if (!appD->qmljsDebugArgumentsString().isEmpty()) { if (!QQmlEnginePrivate::qml_debugging_enabled) { - qWarning() << QString::fromLatin1( + qWarning() << QString(QLatin1String( "QML Debugger: Ignoring \"-qmljsdebugger=%1\". " - "Debugging has not been enabled.").arg( + "Debugging has not been enabled.")).arg( appD->qmljsDebugArgumentsString()); return 0; } @@ -273,9 +273,9 @@ QQmlDebugServer *QQmlDebugServer::instance() if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); - pluginName = QLatin1String("qmldbg_tcp"); + pluginName = QStringLiteral("qmldbg_tcp"); } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) { - pluginName = QLatin1String("qmldbg_ost"); + pluginName = QStringLiteral("qmldbg_ost"); ok = true; } @@ -298,17 +298,17 @@ QQmlDebugServer *QQmlDebugServer::instance() } } else { - qWarning() << QString::fromLatin1( + qWarning() << QString(QLatin1String( "QML Debugger: Ignoring \"-qmljsdebugger=%1\". " - "Format is -qmljsdebugger=port:[,block]").arg( + "Format is -qmljsdebugger=port:[,block]")).arg( appD->qmljsDebugArgumentsString()); } } #else if (!appD->qmljsDebugArgumentsString().isEmpty()) { - qWarning() << QString::fromLatin1( + qWarning() << QString(QLatin1String( "QML Debugger: Ignoring \"-qmljsdebugger=%1\". " - "QtQml is not configured for debugging.").arg( + "QtQml is not configured for debugging.")).arg( appD->qmljsDebugArgumentsString()); } #endif @@ -373,7 +373,7 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message) pluginVersions << service->version(); } - out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << pluginNames << pluginVersions; + out << QString(QStringLiteral("QDeclarativeDebugClient")) << 0 << protocolVersion << pluginNames << pluginVersions; } d->connection->send(QList() << helloAnswer); diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp index a1cc4fe0a3..45948490cf 100644 --- a/src/qml/debugger/qqmldebugservice.cpp +++ b/src/qml/debugger/qqmldebugservice.cpp @@ -216,11 +216,11 @@ bool QQmlDebugService::hasDebuggingClient() QString QQmlDebugService::objectToString(QObject *obj) { if(!obj) - return QLatin1String("NULL"); + return QStringLiteral("NULL"); QString objectName = obj->objectName(); if(objectName.isEmpty()) - objectName = QLatin1String(""); + objectName = QStringLiteral(""); QString rv = QString::fromUtf8(obj->metaObject()->className()) + QLatin1String(": ") + objectName; diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 114d7ef63f..9653cf674f 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -67,7 +67,7 @@ QQmlEngineDebugService *QQmlEngineDebugService::instance() } QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent) - : QQmlDebugService(QLatin1String("QDeclarativeEngine"), 1, parent), + : QQmlDebugService(QStringLiteral("QDeclarativeEngine"), 1, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(0) { @@ -206,12 +206,12 @@ QVariant QQmlEngineDebugService::valueContents(const QVariant &value) const if (o) { QString name = o->objectName(); if (name.isEmpty()) - name = QLatin1String(""); + name = QStringLiteral(""); return name; } } - return QLatin1String(""); + return QStringLiteral(""); } void QQmlEngineDebugService::buildObjectDump(QDataStream &message, @@ -247,7 +247,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message, prop.value = expr->expression(); QObject *scope = expr->scopeObject(); if (scope) { - QString sig = QLatin1String(scope->metaObject()->method(signal->index()).signature()); + QString sig = QString::fromLatin1(scope->metaObject()->method(signal->index()).signature()); int lparen = sig.indexOf(QLatin1Char('(')); if (lparen >= 0) { QString methodName = sig.mid(0, lparen); @@ -510,11 +510,11 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message) bool undefined = false; QVariant value = exprObj.evaluate(&undefined); if (undefined) - result = QLatin1String(""); + result = QString(QStringLiteral("")); else result = valueContents(value); } else { - result = QLatin1String(""); + result = QString(QStringLiteral("")); } QByteArray reply; @@ -667,11 +667,11 @@ void QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, QString paramStr; for (int ii = 0; ii < paramNames.count(); ++ii) { - if (ii != 0) paramStr.append(QLatin1String(",")); + if (ii != 0) paramStr.append(QLatin1Char(',')); paramStr.append(QString::fromUtf8(paramNames.at(ii))); } - QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr + + QString jsfunction = QLatin1String("(function ") + method + QLatin1Char('(') + paramStr + QLatin1String(") {"); jsfunction += body; jsfunction += QLatin1String("\n})"); diff --git a/src/qml/debugger/qqmlinspectorservice.cpp b/src/qml/debugger/qqmlinspectorservice.cpp index c494045bff..5426745bc6 100644 --- a/src/qml/debugger/qqmlinspectorservice.cpp +++ b/src/qml/debugger/qqmlinspectorservice.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QQmlInspectorService, serviceInstance) QQmlInspectorService::QQmlInspectorService() - : QQmlDebugService(QLatin1String("QDeclarativeObserverMode"), 1) + : QQmlDebugService(QStringLiteral("QDeclarativeObserverMode"), 1) , m_currentInspectorPlugin(0) { registerService(); diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp index 2731d2046b..c643073308 100644 --- a/src/qml/debugger/qqmlprofilerservice.cpp +++ b/src/qml/debugger/qqmlprofilerservice.cpp @@ -77,7 +77,7 @@ QByteArray QQmlProfilerData::toByteArray() const } QQmlProfilerService::QQmlProfilerService() - : QQmlDebugService(QLatin1String("CanvasFrameRate"), 1), + : QQmlDebugService(QStringLiteral("CanvasFrameRate"), 1), m_enabled(false), m_messageReceived(false) { m_timer.start(); diff --git a/src/qml/debugger/qv8debugservice.cpp b/src/qml/debugger/qv8debugservice.cpp index ee60bff742..a6aeda31d5 100644 --- a/src/qml/debugger/qv8debugservice.cpp +++ b/src/qml/debugger/qv8debugservice.cpp @@ -120,7 +120,7 @@ public: QV8DebugService::QV8DebugService(QObject *parent) : QQmlDebugService(*(new QV8DebugServicePrivate()), - QLatin1String("V8Debugger"), 2, parent) + QStringLiteral("V8Debugger"), 2, parent) { Q_D(QV8DebugService); v8ServiceInstancePtr = this; diff --git a/src/qml/debugger/qv8profilerservice.cpp b/src/qml/debugger/qv8profilerservice.cpp index 6473a2f4fb..6208676522 100644 --- a/src/qml/debugger/qv8profilerservice.cpp +++ b/src/qml/debugger/qv8profilerservice.cpp @@ -101,7 +101,7 @@ public: }; QV8ProfilerService::QV8ProfilerService(QObject *parent) - : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), 1, parent) + : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QStringLiteral("V8Profiler"), 1, parent) { Q_D(QV8ProfilerService); -- cgit v1.2.3 From 69a1bf164822fe50ced9db1429446e7e84357c1b Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Mon, 12 Mar 2012 10:19:05 +0100 Subject: QmlDebugging: Modify test JSDebug test cases Add signals that are emitted on debugger responses for flaky auto tests. Change-Id: Ic59f559083b2b19fb8eec920dcb76f23125639a8 Reviewed-by: Kai Koehne --- tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 9cd021d5e9..f4a9a4add7 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -303,6 +303,8 @@ signals: void breakAfterCompileRequested(); void result(); void stopped(); + void scriptsResult(); + void evaluateResult(); private: void sendMessage(const QByteArray &); @@ -939,6 +941,12 @@ void QJSDebugClient::messageReceived(const QByteArray &data) } else { // DO NOTHING } + //Emit separate signals for scripts ane evaluate + //as the associated test cases are flaky + if (debugCommand == "scripts") + emit scriptsResult(); + if (debugCommand == "evaluate") + emit evaluateResult(); } else if (type == QLatin1String(EVENT)) { QString event(value.value(QLatin1String(EVENT)).toString()); @@ -1685,8 +1693,8 @@ void tst_QQmlDebugJS::evaluateInGlobalScope() QVERIFY(init()); client->connect(); - client->evaluate(QLatin1String("print('Hello World')"), true); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + client->evaluate(QLatin1String("console.log('Hello World')"), true); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult()))); //Verify the value of 'print' QString jsonString(client->response); @@ -1720,7 +1728,7 @@ void tst_QQmlDebugJS::evaluateInLocalScope() int frameIndex = body.value("index").toInt(); client->evaluate(QLatin1String("root.a"), frameIndex); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(evaluateResult()))); //Verify the value of 'timer.interval' jsonString = client->response; @@ -1759,7 +1767,7 @@ void tst_QQmlDebugJS::getScripts() client->connect(); client->scripts(); - QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult()))); QString jsonString(client->response); QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); -- cgit v1.2.3 From c0f032de776685d62286e8a86496bc03fb9922c9 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 9 Mar 2012 15:22:44 +1000 Subject: Remove unused init function. Change-Id: Id66e177a544fd8e019bae86fff6bd04bd0497d7c Reviewed-by: Yann Bodson --- src/quick/items/qquicktextinput.cpp | 13 ------------- src/quick/items/qquicktextinput_p_p.h | 1 - 2 files changed, 14 deletions(-) diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 1a93345aa2..a06c174e7c 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -2927,19 +2927,6 @@ void QQuickTextInputPrivate::setSelection(int start, int length) | Qt::ImCursorPosition | Qt::ImCurrentSelection); } -/*! - \internal - - Initializes the line control with a starting text value of \a txt. -*/ -void QQuickTextInputPrivate::init(const QString &txt) -{ - m_text = txt; - - updateDisplayText(); - m_cursor = m_text.length(); -} - /*! \internal diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 9a59b44549..bb00600661 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -405,7 +405,6 @@ public: void updateLayout(); private: - void init(const QString &txt); void removeSelectedText(); void internalSetText(const QString &txt, int pos = -1, bool edited = true); void updateDisplayText(bool forceUpdate = false); -- cgit v1.2.3 From a920803631d1788dc563f243a3780899d1ac2af2 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 13 Mar 2012 10:27:59 +0100 Subject: Adding a custom easing curve editor to declarative tools Change-Id: Ic8ef77792d74ec99b23d85cd8888e0190acc3e10 Reviewed-by: Thomas Hartmann Reviewed-by: Alessandro Portale --- tools/easingcurveeditor/Button.qml | 177 +++++++ tools/easingcurveeditor/easingcurveeditor.pro | 25 + tools/easingcurveeditor/main.cpp | 55 ++ tools/easingcurveeditor/mainwindow.cpp | 136 +++++ tools/easingcurveeditor/mainwindow.h | 77 +++ tools/easingcurveeditor/pane.ui | 112 ++++ tools/easingcurveeditor/preview.qml | 148 ++++++ tools/easingcurveeditor/properties.ui | 131 +++++ tools/easingcurveeditor/resources.qrc | 6 + tools/easingcurveeditor/segmentproperties.cpp | 128 +++++ tools/easingcurveeditor/segmentproperties.h | 94 ++++ tools/easingcurveeditor/splineeditor.cpp | 714 ++++++++++++++++++++++++++ tools/easingcurveeditor/splineeditor.h | 143 ++++++ tools/tools.pro | 2 +- 14 files changed, 1947 insertions(+), 1 deletion(-) create mode 100644 tools/easingcurveeditor/Button.qml create mode 100644 tools/easingcurveeditor/easingcurveeditor.pro create mode 100644 tools/easingcurveeditor/main.cpp create mode 100644 tools/easingcurveeditor/mainwindow.cpp create mode 100644 tools/easingcurveeditor/mainwindow.h create mode 100644 tools/easingcurveeditor/pane.ui create mode 100644 tools/easingcurveeditor/preview.qml create mode 100644 tools/easingcurveeditor/properties.ui create mode 100644 tools/easingcurveeditor/resources.qrc create mode 100644 tools/easingcurveeditor/segmentproperties.cpp create mode 100644 tools/easingcurveeditor/segmentproperties.h create mode 100644 tools/easingcurveeditor/splineeditor.cpp create mode 100644 tools/easingcurveeditor/splineeditor.h diff --git a/tools/easingcurveeditor/Button.qml b/tools/easingcurveeditor/Button.qml new file mode 100644 index 0000000000..a47809a2d1 --- /dev/null +++ b/tools/easingcurveeditor/Button.qml @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: button + + signal clicked + + Rectangle { + id: normalBackground + radius: 4 + anchors.fill: parent + smooth: true + gradient: Gradient { + GradientStop { + position: 0 + color: "#afafaf" + } + + GradientStop { + position: 0.460 + color: "#808080" + } + + GradientStop { + position: 1 + color: "#adadad" + } + } + border.color: "#000000" + } + + + Rectangle { + id: hoveredBackground + x: 2 + y: -8 + radius: 4 + opacity: 0 + gradient: Gradient { + GradientStop { + position: 0 + color: "#cacaca" + } + + GradientStop { + position: 0.460 + color: "#a2a2a2" + } + + GradientStop { + position: 1 + color: "#c8c8c8" + } + } + smooth: true + anchors.fill: parent + border.color: "#000000" + } + + + Rectangle { + id: pressedBackground + x: -8 + y: 2 + radius: 4 + opacity: 0 + gradient: Gradient { + GradientStop { + position: 0 + color: "#8b8b8b" + } + + GradientStop { + position: 0.470 + color: "#626161" + } + + GradientStop { + position: 1 + color: "#8f8e8e" + } + } + smooth: true + anchors.fill: parent + border.color: "#000000" + } + states: [ + State { + name: "hovered" + + PropertyChanges { + target: normalBackground + opacity: 0 + } + + PropertyChanges { + target: hoveredBackground + opacity: 1 + } + }, + State { + name: "pressed" + + PropertyChanges { + target: normalBackground + opacity: 0 + } + + PropertyChanges { + target: pressedBackground + opacity: 1 + } + } + ] + + Text { + color: "#e8e8e8" + text: qsTr("Play") + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.bold: true + font.pixelSize: 20 + } + + MouseArea { + hoverEnabled: true + anchors.fill: parent + onEntered: button.state = "hovered" + onExited: button.state = "" + onClicked: { + button.state = "pressed" + button.clicked(); + } + } +} diff --git a/tools/easingcurveeditor/easingcurveeditor.pro b/tools/easingcurveeditor/easingcurveeditor.pro new file mode 100644 index 0000000000..0a266d0aee --- /dev/null +++ b/tools/easingcurveeditor/easingcurveeditor.pro @@ -0,0 +1,25 @@ +TEMPLATE = app +DEPENDPATH += . +INCLUDEPATH += . + +QT += declarative quick widgets +CONFIG -= app_bundle + +# Input +SOURCES += main.cpp \ + splineeditor.cpp \ + mainwindow.cpp \ + segmentproperties.cpp + +RESOURCES = $$PWD/resources.qrc + +HEADERS += \ + splineeditor.h \ + mainwindow.h \ + ui_properties.h \ + ui_pane.h \ + segmentproperties.h + +FORMS += \ + properties.ui \ + pane.ui diff --git a/tools/easingcurveeditor/main.cpp b/tools/easingcurveeditor/main.cpp new file mode 100644 index 0000000000..05e8ace53a --- /dev/null +++ b/tools/easingcurveeditor/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + + +int main(int argc, char ** argv) +{ + QApplication app(argc, argv); + + MainWindow mainWindow; + mainWindow.show(); + mainWindow.showQuickView(); + + return app.exec(); +} diff --git a/tools/easingcurveeditor/mainwindow.cpp b/tools/easingcurveeditor/mainwindow.cpp new file mode 100644 index 0000000000..569b74ae29 --- /dev/null +++ b/tools/easingcurveeditor/mainwindow.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "splineeditor.h" +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent) +{ + SplineEditor *splineEditor = new SplineEditor(this); + + QWidget *mainWidget = new QWidget(this); + + setCentralWidget(mainWidget); + + QHBoxLayout *hboxLayout = new QHBoxLayout(mainWidget); + QVBoxLayout *vboxLayout = new QVBoxLayout(); + + mainWidget->setLayout(hboxLayout); + hboxLayout->addLayout(vboxLayout); + + QWidget *propertyWidget = new QWidget(this); + ui_properties.setupUi(propertyWidget); + + ui_properties.spinBox->setMinimum(50); + ui_properties.spinBox->setMaximum(10000); + ui_properties.spinBox->setValue(500); + + hboxLayout->addWidget(propertyWidget); + + m_placeholder = new QWidget(this); + + m_placeholder->setFixedSize(quickView.size()); + + vboxLayout->addWidget(splineEditor); + vboxLayout->addWidget(m_placeholder); + + ui_properties.plainTextEdit->setPlainText(splineEditor->generateCode()); + connect(splineEditor, SIGNAL(easingCurveCodeChanged(QString)), ui_properties.plainTextEdit, SLOT(setPlainText(QString))); + + quickView.rootContext()->setContextProperty(QLatin1String("spinBox"), ui_properties.spinBox); + + foreach (const QString &name, splineEditor->presetNames()) + ui_properties.comboBox->addItem(name); + + connect(ui_properties.comboBox, SIGNAL(currentIndexChanged(QString)), splineEditor, SLOT(setPreset(QString))); + + splineEditor->setPreset(ui_properties.comboBox->currentText()); + + QVBoxLayout *groupBoxLayout = new QVBoxLayout(ui_properties.groupBox); + groupBoxLayout->setMargin(0); + ui_properties.groupBox->setLayout(groupBoxLayout); + + groupBoxLayout->addWidget(splineEditor->pointListWidget()); + m_splineEditor = splineEditor; + connect(ui_properties.plainTextEdit, SIGNAL(textChanged()), this, SLOT(textEditTextChanged())); + initQml(); +} + +void MainWindow::showQuickView() +{ + const int margin = 16; + quickView.move(pos() + QPoint(0, frameGeometry().height() + margin)); + + quickView.raise(); + quickView.show(); +} + +void MainWindow::textEditTextChanged() +{ + m_splineEditor->setEasingCurve(ui_properties.plainTextEdit->toPlainText().trimmed()); +} + +void MainWindow::moveEvent(QMoveEvent *event) +{ + QMainWindow::moveEvent(event); + showQuickView(); +} + +void MainWindow::resizeEvent(QResizeEvent *event) +{ + QMainWindow::resizeEvent(event); + showQuickView(); +} + +void MainWindow::initQml() +{ + quickView.setWindowFlags(Qt::FramelessWindowHint); + quickView.rootContext()->setContextProperty(QLatin1String("editor"), m_splineEditor); + quickView.setSource(QUrl("qrc:/preview.qml")); + quickView.show(); +} diff --git a/tools/easingcurveeditor/mainwindow.h b/tools/easingcurveeditor/mainwindow.h new file mode 100644 index 0000000000..44591d33cc --- /dev/null +++ b/tools/easingcurveeditor/mainwindow.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "ui_properties.h" + +class SplineEditor; + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit MainWindow(QWidget *parent = 0); + + void showQuickView(); + +signals: + +public slots: + void textEditTextChanged(); + +protected: + virtual void moveEvent(QMoveEvent *event); + virtual void resizeEvent(QResizeEvent *event); + void initQml(); + +private: + QQuickView quickView; + QWidget *m_placeholder; + Ui_Properties ui_properties; + SplineEditor *m_splineEditor; + +}; + +#endif // MAINWINDOW_H diff --git a/tools/easingcurveeditor/pane.ui b/tools/easingcurveeditor/pane.ui new file mode 100644 index 0000000000..1500589192 --- /dev/null +++ b/tools/easingcurveeditor/pane.ui @@ -0,0 +1,112 @@ + + + Pane + + + + 0 + 0 + 416 + 47 + + + + + 0 + 0 + + + + Form + + + + + + + 75 + true + + + + p1 + + + + + + + + 4 + + + 2 + + + + + x + + + + + + + 4 + + + 0.010000000000000 + + + + + + + y + + + + + + + 4 + + + -10.000000000000000 + + + 10.000000000000000 + + + 0.010000000000000 + + + + + + + + + + smooth + + + + + + + Qt::Horizontal + + + + 99 + 10 + + + + + + + + + diff --git a/tools/easingcurveeditor/preview.qml b/tools/easingcurveeditor/preview.qml new file mode 100644 index 0000000000..61f4862e76 --- /dev/null +++ b/tools/easingcurveeditor/preview.qml @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: root + width: 800 + height: 100 + + Rectangle { + gradient: Gradient { + GradientStop { + position: 0 + color: "#aaa7a7" + } + + GradientStop { + position: 0.340 + color: "#a4a4a4" + } + + GradientStop { + position: 1 + color: "#6b6b6b" + } + } + anchors.fill: parent + } + + Button { + id: button + + x: 19 + y: 20 + width: 133 + height: 61 + onClicked: { + if (root.state ==="") + root.state = "moved"; + else + root.state = ""; + } + } + + Rectangle { + id: groove + x: 163 + y: 20 + width: 622 + height: 61 + color: "#919191" + radius: 4 + border.color: "#adadad" + + Rectangle { + id: rectangle + x: 9 + y: 9 + width: 46 + height: 46 + color: "#3045b7" + radius: 4 + border.width: 2 + smooth: true + border.color: "#9ea0bb" + anchors.bottomMargin: 6 + anchors.topMargin: 9 + anchors.top: parent.top + anchors.bottom: parent.bottom + } + } + states: [ + State { + name: "moved" + + PropertyChanges { + target: rectangle + x: 567 + y: 9 + anchors.bottomMargin: 6 + anchors.topMargin: 9 + } + } + ] + + transitions: [ + Transition { + from: "" + to: "moved" + SequentialAnimation { + PropertyAnimation { + easing: editor.easingCurve + property: "x" + duration: spinBox.value + } + } + }, + Transition { + from: "moved" + to: "" + PropertyAnimation { + easing: editor.easingCurve + property: "x" + duration: spinBox.value + } + + } + ] +} diff --git a/tools/easingcurveeditor/properties.ui b/tools/easingcurveeditor/properties.ui new file mode 100644 index 0000000000..af96e9c7a1 --- /dev/null +++ b/tools/easingcurveeditor/properties.ui @@ -0,0 +1,131 @@ + + + Properties + + + + 0 + 0 + 487 + 627 + + + + + 0 + 0 + + + + Form + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + + + + Duration + + + + + + + + + + Code + + + + + + + + 16777215 + 128 + + + + false + + + + + + + + + + Presets + + + + + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + + 400 + 0 + + + + Control Points + + + true + + + + + + + + diff --git a/tools/easingcurveeditor/resources.qrc b/tools/easingcurveeditor/resources.qrc new file mode 100644 index 0000000000..c184af4662 --- /dev/null +++ b/tools/easingcurveeditor/resources.qrc @@ -0,0 +1,6 @@ + + + preview.qml + Button.qml + + diff --git a/tools/easingcurveeditor/segmentproperties.cpp b/tools/easingcurveeditor/segmentproperties.cpp new file mode 100644 index 0000000000..886d4636aa --- /dev/null +++ b/tools/easingcurveeditor/segmentproperties.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "segmentproperties.h" +#include "splineeditor.h" + +SegmentProperties::SegmentProperties(QWidget *parent) : + QWidget(parent), m_splineEditor(0), m_blockSignals(false) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(2); + setLayout(layout); + { + QWidget *widget = new QWidget(this); + m_ui_pane_c1.setupUi(widget); + m_ui_pane_c1.label->setText("c1"); + m_ui_pane_c1.smooth->setVisible(false); + layout->addWidget(widget); + + connect(m_ui_pane_c1.p1_x, SIGNAL(valueChanged(double)), this, SLOT(c1Updated())); + connect(m_ui_pane_c1.p1_y, SIGNAL(valueChanged(double)), this, SLOT(c1Updated())); + } + { + QWidget *widget = new QWidget(this); + m_ui_pane_c2.setupUi(widget); + m_ui_pane_c2.label->setText("c2"); + m_ui_pane_c2.smooth->setVisible(false); + layout->addWidget(widget); + + connect(m_ui_pane_c2.p1_x, SIGNAL(valueChanged(double)), this, SLOT(c2Updated())); + connect(m_ui_pane_c2.p1_y, SIGNAL(valueChanged(double)), this, SLOT(c2Updated())); + } + { + QWidget *widget = new QWidget(this); + m_ui_pane_p.setupUi(widget); + m_ui_pane_p.label->setText("p1"); + layout->addWidget(widget); + + connect(m_ui_pane_p.smooth, SIGNAL(toggled(bool)), this, SLOT(pUpdated())); + connect(m_ui_pane_p.p1_x, SIGNAL(valueChanged(double)), this, SLOT(pUpdated())); + connect(m_ui_pane_p.p1_y, SIGNAL(valueChanged(double)), this, SLOT(pUpdated())); + } +} + +void SegmentProperties::c1Updated() +{ + if (m_splineEditor && !m_blockSignals) { + QPointF c1(m_ui_pane_c1.p1_x->value(), m_ui_pane_c1.p1_y->value()); + m_splineEditor->setControlPoint(m_segment * 3, c1); + } +} + +void SegmentProperties::c2Updated() +{ + if (m_splineEditor && !m_blockSignals) { + QPointF c2(m_ui_pane_c2.p1_x->value(), m_ui_pane_c2.p1_y->value()); + m_splineEditor->setControlPoint(m_segment * 3 + 1, c2); + } +} + +void SegmentProperties::pUpdated() +{ + if (m_splineEditor && !m_blockSignals) { + QPointF p(m_ui_pane_p.p1_x->value(), m_ui_pane_p.p1_y->value()); + bool smooth = m_ui_pane_p.smooth->isChecked(); + m_splineEditor->setControlPoint(m_segment * 3 + 2, p); + m_splineEditor->setSmooth(m_segment, smooth); + } +} + +void SegmentProperties::invalidate() +{ + m_blockSignals = true; + + m_ui_pane_p.label->setText(QLatin1String("p") + QString::number(m_segment)); + m_ui_pane_p.smooth->setChecked(m_smooth); + m_ui_pane_p.smooth->parentWidget()->setEnabled(!m_last); + + m_ui_pane_c1.p1_x->setValue(m_points.at(0).x()); + m_ui_pane_c1.p1_y->setValue(m_points.at(0).y()); + + m_ui_pane_c2.p1_x->setValue(m_points.at(1).x()); + m_ui_pane_c2.p1_y->setValue(m_points.at(1).y()); + + m_ui_pane_p.p1_x->setValue(m_points.at(2).x()); + m_ui_pane_p.p1_y->setValue(m_points.at(2).y()); + + m_blockSignals = false; +} diff --git a/tools/easingcurveeditor/segmentproperties.h b/tools/easingcurveeditor/segmentproperties.h new file mode 100644 index 0000000000..4d86be3882 --- /dev/null +++ b/tools/easingcurveeditor/segmentproperties.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SEGMENTPROPERTIES_H +#define SEGMENTPROPERTIES_H + +#include +#include + +class SplineEditor; + +class SegmentProperties : public QWidget +{ + Q_OBJECT +public: + explicit SegmentProperties(QWidget *parent = 0); + void setSplineEditor(SplineEditor *splineEditor) + { + m_splineEditor = splineEditor; + } + + void setSegment(int segment, QVector points, bool smooth, bool last) + { + m_segment = segment; + m_points = points; + m_smooth = smooth; + m_last = last; + invalidate(); + } + +signals: + +public slots: + +private slots: + void c1Updated(); + void c2Updated(); + void pUpdated(); + +private: + void invalidate(); + + Ui_Pane m_ui_pane_c1; + Ui_Pane m_ui_pane_c2; + Ui_Pane m_ui_pane_p; + + SplineEditor *m_splineEditor; + QVector m_points; + int m_segment; + bool m_smooth; + bool m_last; + + bool m_blockSignals; +}; + +#endif // SEGMENTPROPERTIES_H diff --git a/tools/easingcurveeditor/splineeditor.cpp b/tools/easingcurveeditor/splineeditor.cpp new file mode 100644 index 0000000000..dbd32dd63a --- /dev/null +++ b/tools/easingcurveeditor/splineeditor.cpp @@ -0,0 +1,714 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "splineeditor.h" + +#include +#include +#include +#include +#include +#include + +const int canvasWidth = 640; +const int canvasHeight = 320; + +const int canvasMargin = 160; + +SplineEditor::SplineEditor(QWidget *parent) : + QWidget(parent), m_pointListWidget(0), m_block(false) +{ + setFixedSize(canvasWidth + canvasMargin * 2, canvasHeight + canvasMargin * 2); + + m_controlPoints.append(QPointF(0.4, 0.075)); + m_controlPoints.append(QPointF(0.45,0.24)); + m_controlPoints.append(QPointF(0.5,0.5)); + + m_controlPoints.append(QPointF(0.55,0.76)); + m_controlPoints.append(QPointF(0.7,0.9)); + m_controlPoints.append(QPointF(1.0, 1.0)); + + m_numberOfSegments = 2; + + m_activeControlPoint = -1; + + m_mouseDrag = false; + + m_pointContextMenu = new QMenu(this); + m_deleteAction = new QAction(tr("Delete point"), m_pointContextMenu); + m_smoothAction = new QAction(tr("Smooth point"), m_pointContextMenu); + m_cornerAction = new QAction(tr("Corner point"), m_pointContextMenu); + + m_smoothAction->setCheckable(true); + + m_pointContextMenu->addAction(m_deleteAction); + m_pointContextMenu->addAction(m_smoothAction); + m_pointContextMenu->addAction(m_cornerAction); + + m_curveContextMenu = new QMenu(this); + + m_addPoint = new QAction(tr("Add point"), m_pointContextMenu); + + m_curveContextMenu->addAction(m_addPoint); + + initPresets(); + + invalidateSmoothList(); +} + +static inline QPointF mapToCanvas(const QPointF &point) +{ + return QPointF(point.x() * canvasWidth + canvasMargin, + canvasHeight - point.y() * canvasHeight + canvasMargin); +} + +static inline QPointF mapFromCanvas(const QPointF &point) +{ + return QPointF((point.x() - canvasMargin) / canvasWidth , + 1 - (point.y() - canvasMargin) / canvasHeight); +} + +static inline void paintControlPoint(const QPointF &controlPoint, QPainter *painter, bool edit, + bool realPoint, bool active, bool smooth) +{ + int pointSize = 4; + + if (active) + painter->setBrush(QColor(140, 140, 240, 255)); + else + painter->setBrush(QColor(120, 120, 220, 255)); + + if (realPoint) { + pointSize = 6; + painter->setBrush(QColor(80, 80, 210, 150)); + } + + painter->setPen(QColor(50, 50, 50, 140)); + + if (!edit) + painter->setBrush(QColor(160, 80, 80, 250)); + + if (smooth) { + painter->drawEllipse(QRectF(mapToCanvas(controlPoint).x() - pointSize + 0.5, + mapToCanvas(controlPoint).y() - pointSize + 0.5, + pointSize * 2, pointSize * 2)); + } else { + painter->drawRect(QRectF(mapToCanvas(controlPoint).x() - pointSize + 0.5, + mapToCanvas(controlPoint).y() - pointSize + 0.5, + pointSize * 2, pointSize * 2)); + } +} + +static inline bool indexIsRealPoint(int i) +{ + return !((i + 1) % 3); +} + +static inline int pointForControlPoint(int i) +{ + if ((i % 3) == 0) + return i - 1; + + if ((i % 3) == 1) + return i + 1; + + return i; +} + +void drawCleanLine(QPainter *painter, const QPoint p1, QPoint p2) +{ + painter->drawLine(p1 + QPointF(0.5 , 0.5), p2 + QPointF(0.5, 0.5)); +} + +void SplineEditor::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + + QPen pen(Qt::black); + pen.setWidth(1); + painter.fillRect(0,0,width() - 1, height() - 1, QBrush(Qt::white)); + painter.drawRect(0,0,width() - 1, height() - 1); + + painter.setRenderHint(QPainter::Antialiasing); + + pen = QPen(Qt::gray); + pen.setWidth(1); + pen.setStyle(Qt::DashLine); + painter.setPen(pen); + drawCleanLine(&painter,mapToCanvas(QPoint(0, 0)).toPoint(), mapToCanvas(QPoint(1, 0)).toPoint()); + drawCleanLine(&painter,mapToCanvas(QPoint(0, 1)).toPoint(), mapToCanvas(QPoint(1, 1)).toPoint()); + + for (int i = 0; i < m_numberOfSegments; i++) { + QPainterPath path; + QPointF p0; + + if (i == 0) + p0 = mapToCanvas(QPointF(0.0, 0.0)); + else + p0 = mapToCanvas(m_controlPoints.at(i * 3 - 1)); + + path.moveTo(p0); + + QPointF p1 = mapToCanvas(m_controlPoints.at(i * 3)); + QPointF p2 = mapToCanvas(m_controlPoints.at(i * 3 + 1)); + QPointF p3 = mapToCanvas(m_controlPoints.at(i * 3 + 2)); + path.cubicTo(p1, p2, p3); + painter.strokePath(path, QPen(QBrush(Qt::black), 2)); + + QPen pen(Qt::black); + pen.setWidth(1); + pen.setStyle(Qt::DashLine); + painter.setPen(pen); + painter.drawLine(p0, p1); + painter.drawLine(p3, p2); + } + + paintControlPoint(QPointF(0.0, 0.0), &painter, false, true, false, false); + paintControlPoint(QPointF(1.0, 1.0), &painter, false, true, false, false); + + for (int i = 0; i < m_controlPoints.count() - 1; ++i) + paintControlPoint(m_controlPoints.at(i), + &painter, + true, + indexIsRealPoint(i), + i == m_activeControlPoint, + isControlPointSmooth(i)); +} + +void SplineEditor::mousePressEvent(QMouseEvent *e) +{ + if (e->button() == Qt::LeftButton) { + m_activeControlPoint = findControlPoint(e->pos()); + + if (m_activeControlPoint != -1) { + mouseMoveEvent(e); + } + m_mousePress = e->pos(); + e->accept(); + } +} + +void SplineEditor::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() == Qt::LeftButton) { + m_activeControlPoint = -1; + + m_mouseDrag = false; + e->accept(); + } +} + +void SplineEditor::contextMenuEvent(QContextMenuEvent *e) +{ + int index = findControlPoint(e->pos()); + + if (index > 0 && indexIsRealPoint(index)) { + m_smoothAction->setChecked(isControlPointSmooth(index)); + QAction* action = m_pointContextMenu->exec(e->globalPos()); + if (action == m_deleteAction) + deletePoint(index); + else if (action == m_smoothAction) + smoothPoint(index); + else if (action == m_cornerAction) + cornerPoint(index); + } else { + QAction* action = m_curveContextMenu->exec(e->globalPos()); + if (action == m_addPoint) + addPoint(e->pos()); + } +} + +void SplineEditor::invalidate() +{ + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + + for (int i = 0; i < m_numberOfSegments; ++i) { + easingCurve.addCubicBezierSegment(m_controlPoints.at(i * 3), + m_controlPoints.at(i * 3 + 1), + m_controlPoints.at(i * 3 + 2)); + } + setEasingCurve(easingCurve); + invalidateSegmentProperties(); +} + +void SplineEditor::invalidateSmoothList() +{ + m_smoothList.clear(); + + for (int i = 0; i < (m_numberOfSegments - 1); ++i) + m_smoothList.append(isSmooth(i * 3 + 2)); + +} + +void SplineEditor::invalidateSegmentProperties() +{ + for (int i = 0; i < m_numberOfSegments; ++i) { + SegmentProperties *segmentProperties = m_segmentProperties.at(i); + bool smooth = false; + if (i < (m_numberOfSegments - 1)) { + smooth = m_smoothList.at(i); + } + segmentProperties->setSegment(i, m_controlPoints.mid(i * 3, 3), smooth, i == (m_numberOfSegments - 1)); + } +} + +QHash SplineEditor::presets() const +{ + return m_presets; +} + +QString SplineEditor::generateCode() +{ + QString s = QLatin1String("["); + foreach (const QPointF &point, m_controlPoints) { + s += QString::number(point.x(), 'g', 2) + "," + QString::number(point.y(), 'g', 3) + ","; + } + s.chop(1); //removing last "," + s += "]"; + + return s; +} + +QStringList SplineEditor::presetNames() const +{ + return m_presets.keys(); +} + +QWidget *SplineEditor::pointListWidget() +{ + if (!m_pointListWidget) { + setupPointListWidget(); + } + + return m_pointListWidget; +} + +int SplineEditor::findControlPoint(const QPoint &point) +{ + int pointIndex = -1; + qreal distance = -1; + for (int i = 0; iisChecked()) { + + QPointF before = QPointF(0,0); + if (index > 3) + before = m_controlPoints.at(index - 3); + + QPointF after = QPointF(1.0, 1.0); + if ((index + 3) < m_controlPoints.count()) + after = m_controlPoints.at(index + 3); + + QPointF tangent = (after - before) / 6; + + QPointF thisPoint = m_controlPoints.at(index); + + if (index > 0) + m_controlPoints[index - 1] = thisPoint - tangent; + + if (index + 1 < m_controlPoints.count()) + m_controlPoints[index + 1] = thisPoint + tangent; + + m_smoothList[index / 3] = true; + } else { + m_smoothList[index / 3] = false; + } + invalidate(); + update(); +} + +void SplineEditor::cornerPoint(int index) +{ + QPointF before = QPointF(0,0); + if (index > 3) + before = m_controlPoints.at(index - 3); + + QPointF after = QPointF(1.0, 1.0); + if ((index + 3) < m_controlPoints.count()) + after = m_controlPoints.at(index + 3); + + QPointF thisPoint = m_controlPoints.at(index); + + if (index > 0) + m_controlPoints[index - 1] = (before - thisPoint) / 3 + thisPoint; + + if (index + 1 < m_controlPoints.count()) + m_controlPoints[index + 1] = (after - thisPoint) / 3 + thisPoint; + + m_smoothList[(index) / 3] = false; + invalidate(); +} + +void SplineEditor::deletePoint(int index) +{ + m_controlPoints.remove(index - 1, 3); + m_numberOfSegments--; + + invalidateSmoothList(); + setupPointListWidget(); + invalidate(); +} + +void SplineEditor::addPoint(const QPointF point) +{ + QPointF newPos = mapFromCanvas(point); + int splitIndex = 0; + for (int i=0; i < m_controlPoints.size() - 1; ++i) { + if (indexIsRealPoint(i) && m_controlPoints.at(i).x() > newPos.x()) { + break; + } else if (indexIsRealPoint(i)) + splitIndex = i; + } + QPointF before = QPointF(0,0); + if (splitIndex > 0) + before = m_controlPoints.at(splitIndex); + + QPointF after = QPointF(1.0, 1.0); + if ((splitIndex + 3) < m_controlPoints.count()) + after = m_controlPoints.at(splitIndex + 3); + + if (splitIndex > 0) { + m_controlPoints.insert(splitIndex + 2, (newPos + after) / 2); + m_controlPoints.insert(splitIndex + 2, newPos); + m_controlPoints.insert(splitIndex + 2, (newPos + before) / 2); + } else { + m_controlPoints.insert(splitIndex + 1, (newPos + after) / 2); + m_controlPoints.insert(splitIndex + 1, newPos); + m_controlPoints.insert(splitIndex + 1, (newPos + before) / 2); + } + m_numberOfSegments++; + + invalidateSmoothList(); + setupPointListWidget(); + invalidate(); +} + +void SplineEditor::initPresets() +{ + const QPointF endPoint(1.0, 1.0); + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF(0.4, 0.075), QPointF(0.45, 0.24), QPointF(0.5, 0.5)); + easingCurve.addCubicBezierSegment(QPointF(0.55, 0.76), QPointF(0.7, 0.9), endPoint); + m_presets.insert(tr("Standard Easing"), easingCurve); + } + + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF(0.43, 0.0025), QPointF(0.65, 1), endPoint); + m_presets.insert(tr("Simple"), easingCurve); + } + + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF(0.43, 0.0025), QPointF(0.38, 0.51), QPointF(0.57, 0.99)); + easingCurve.addCubicBezierSegment(QPointF(0.8, 0.69), QPointF(0.65, 1), endPoint); + m_presets.insert(tr("Simple Bounce"), easingCurve); + } + + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF(0.4, 0.075), QPointF(0.64, -0.0025), QPointF(0.74, 0.23)); + easingCurve.addCubicBezierSegment(QPointF(0.84, 0.46), QPointF(0.91, 0.77), endPoint); + m_presets.insert(tr("Slow in fast out"), easingCurve); + } + + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF(0.43, 0.0025), QPointF(0.47, 0.51), QPointF(0.59, 0.94)); + easingCurve.addCubicBezierSegment(QPointF(0.84, 0.95), QPointF( 0.99, 0.94), endPoint); + m_presets.insert(tr("Snapping"), easingCurve); + } + + { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + easingCurve.addCubicBezierSegment(QPointF( 0.38, 0.35),QPointF(0.38, 0.7), QPointF(0.45, 0.99)); + easingCurve.addCubicBezierSegment(QPointF(0.48, 0.66), QPointF(0.62, 0.62), QPointF(0.66, 0.99)); + easingCurve.addCubicBezierSegment(QPointF(0.69, 0.76), QPointF(0.77, 0.76), QPointF(0.79, 0.99)); + easingCurve.addCubicBezierSegment(QPointF(0.83, 0.91), QPointF(0.87, 0.92), QPointF(0.91, 0.99)); + easingCurve.addCubicBezierSegment(QPointF(0.95, 0.95), QPointF(0.97, 0.94), endPoint); + m_presets.insert(tr("Complex Bounce"), easingCurve); + } + + { + QEasingCurve easingCurve4(QEasingCurve::BezierSpline); + easingCurve4.addCubicBezierSegment(QPointF(0.12, -0.12),QPointF(0.23, -0.19), QPointF( 0.35, -0.09)); + easingCurve4.addCubicBezierSegment(QPointF(0.47, 0.005), QPointF(0.52, 1), QPointF(0.62, 1.1)); + easingCurve4.addCubicBezierSegment(QPointF(0.73, 1.2), QPointF(0.91,1 ), endPoint); + m_presets.insert(tr("Overshoot"), easingCurve4); + } +} + +void SplineEditor::setupPointListWidget() +{ + if (!m_pointListWidget) + m_pointListWidget = new QScrollArea(this); + + if (m_pointListWidget->widget()) + delete m_pointListWidget->widget(); + + m_pointListWidget->setFrameStyle(QFrame::NoFrame); + m_pointListWidget->setWidgetResizable(true); + m_pointListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_pointListWidget->setWidget(new QWidget(m_pointListWidget)); + QVBoxLayout *layout = new QVBoxLayout(m_pointListWidget->widget()); + layout->setMargin(0); + layout->setSpacing(2); + m_pointListWidget->widget()->setLayout(layout); + + m_segmentProperties.clear(); + + { //implicit 0,0 + QWidget *widget = new QWidget(m_pointListWidget->widget()); + Ui_Pane pane; + pane.setupUi(widget); + pane.p1_x->setValue(0); + pane.p1_y->setValue(0); + layout->addWidget(widget); + pane.label->setText("p0"); + widget->setEnabled(false); + } + + for (int i = 0; i < m_numberOfSegments; ++i) { + SegmentProperties *segmentProperties = new SegmentProperties(m_pointListWidget->widget()); + layout->addWidget(segmentProperties); + bool smooth = false; + if (i < (m_numberOfSegments - 1)) { + smooth = m_smoothList.at(i); + } + segmentProperties->setSegment(i, m_controlPoints.mid(i * 3, 3), smooth, i == (m_numberOfSegments - 1)); + segmentProperties->setSplineEditor(this); + m_segmentProperties << segmentProperties; + } + layout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding)); + + m_pointListWidget->viewport()->show(); + m_pointListWidget->viewport()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + m_pointListWidget->show(); +} + +bool SplineEditor::isControlPointSmooth(int i) const +{ + if (i == 0) + return false; + + if (i == m_controlPoints.count() - 1) + return false; + + if (m_numberOfSegments == 1) + return false; + + int index = pointForControlPoint(i); + + if (index == 0) + return false; + + if (index == m_controlPoints.count() - 1) + return false; + + return m_smoothList.at(index / 3); +} + +QPointF limitToCanvas(const QPointF point) +{ + qreal left = -qreal( canvasMargin) / qreal(canvasWidth); + qreal width = 1.0 - 2.0 * left; + + qreal top = -qreal( canvasMargin) / qreal(canvasHeight); + qreal height = 1.0 - 2.0 * top; + + QPointF p = point; + QRectF r(left, top, width, height); + + if (p.x() > r.right()) { + p.setX(r.right()); + } + if (p.x() < r.left()) { + p.setX(r.left()); + } + if (p.y() < r.top()) { + p.setY(r.top()); + } + if (p.y() > r.bottom()) { + p.setY(r.bottom()); + } + return p; +} + +void SplineEditor::mouseMoveEvent(QMouseEvent *e) +{ + // If we've moved more then 25 pixels, assume user is dragging + if (!m_mouseDrag && QPoint(m_mousePress - e->pos()).manhattanLength() > qApp->startDragDistance()) + m_mouseDrag = true; + + QPointF p = mapFromCanvas(e->pos()); + + if (m_mouseDrag && m_activeControlPoint >= 0 && m_activeControlPoint < m_controlPoints.size()) { + p = limitToCanvas(p); + if (indexIsRealPoint(m_activeControlPoint)) { + //move also the tangents + QPointF targetPoint = p; + QPointF distance = targetPoint - m_controlPoints[m_activeControlPoint]; + m_controlPoints[m_activeControlPoint] = targetPoint; + m_controlPoints[m_activeControlPoint - 1] += distance; + m_controlPoints[m_activeControlPoint + 1] += distance; + } else { + if (!isControlPointSmooth(m_activeControlPoint)) { + m_controlPoints[m_activeControlPoint] = p; + } else { + QPointF targetPoint = p; + QPointF distance = targetPoint - m_controlPoints[m_activeControlPoint]; + m_controlPoints[m_activeControlPoint] = p; + + if ((m_activeControlPoint > 1) && (m_activeControlPoint % 3) == 0) { //right control point + m_controlPoints[m_activeControlPoint - 2] -= distance; + } else if ((m_activeControlPoint < (m_controlPoints.count() - 2)) //left control point + && (m_activeControlPoint % 3) == 1) { + m_controlPoints[m_activeControlPoint + 2] -= distance; + } + } + } + invalidate(); + } +} + +void SplineEditor::setEasingCurve(const QEasingCurve &easingCurve) +{ + if (m_easingCurve == easingCurve) + return; + m_block = true; + m_easingCurve = easingCurve; + m_controlPoints = m_easingCurve.cubicBezierSpline().toVector(); + m_numberOfSegments = m_controlPoints.count() / 3; + update(); + emit easingCurveChanged(); + + const QString code = generateCode(); + emit easingCurveCodeChanged(code); + + m_block = false; +} + +void SplineEditor::setPreset(const QString &name) +{ + setEasingCurve(m_presets.value(name)); + invalidateSmoothList(); + setupPointListWidget(); +} + +void SplineEditor::setEasingCurve(const QString &code) +{ + if (m_block) + return; + if (code.left(1) == QLatin1String("[") && code.right(1) == QLatin1String("]")) { + QString cleanCode = code; + cleanCode.remove(0, 1); + cleanCode.chop(1); + const QStringList stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts); + if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) { + QList realList; + foreach (const QString &string, stringList) { + bool ok; + realList.append(string.toDouble(&ok)); + if (!ok) + return; + } + QList points; + for (int i = 0; i < realList.count() / 2; ++i) + points.append(QPointF(realList.at(i * 2), realList.at(i * 2 + 1))); + if (points.last() == QPointF(1.0, 1.0)) { + QEasingCurve easingCurve(QEasingCurve::BezierSpline); + + for (int i = 0; i < points.count() / 3; ++i) { + easingCurve.addCubicBezierSegment(points.at(i * 3), + points.at(i * 3 + 1), + points.at(i * 3 + 2)); + } + setEasingCurve(easingCurve); + invalidateSmoothList(); + setupPointListWidget(); + } + } + } +} diff --git a/tools/easingcurveeditor/splineeditor.h b/tools/easingcurveeditor/splineeditor.h new file mode 100644 index 0000000000..81f2dfd1ce --- /dev/null +++ b/tools/easingcurveeditor/splineeditor.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SPLINEEDITOR_H +#define SPLINEEDITOR_H + +#include +#include +#include +#include + +#include +#include + +class SegmentProperties; + +class SplineEditor : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve NOTIFY easingCurveChanged); + +public: + explicit SplineEditor(QWidget *parent = 0); + QString generateCode(); + QStringList presetNames() const; + QWidget *pointListWidget(); + + void setControlPoint(int index, const QPointF &point) + { + m_controlPoints[index] = point; + update(); + } + + void setSmooth(int index, bool smooth) + { + m_smoothAction->setChecked(smooth); + smoothPoint(index * 3 + 2); + //update(); + } + +signals: + void easingCurveChanged(); + void easingCurveCodeChanged(const QString &code); + + +public slots: + void setEasingCurve(const QEasingCurve &easingCurve); + void setPreset(const QString &name); + void setEasingCurve(const QString &code); + +protected: + void paintEvent(QPaintEvent *); + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void contextMenuEvent(QContextMenuEvent *); + + void invalidate(); + void invalidateSmoothList(); + void invalidateSegmentProperties(); + + QEasingCurve easingCurve() const + { return m_easingCurve; } + + QHash presets() const; + +private: + int findControlPoint(const QPoint &point); + bool isSmooth(int i) const; + + void smoothPoint( int index); + void cornerPoint( int index); + void deletePoint(int index); + void addPoint(const QPointF point); + + void initPresets(); + + void setupPointListWidget(); + + bool isControlPointSmooth(int i) const; + + QEasingCurve m_easingCurve; + QVector m_controlPoints; + QVector m_smoothList; + int m_numberOfSegments; + int m_activeControlPoint; + bool m_mouseDrag; + QPoint m_mousePress; + QHash m_presets; + + QMenu *m_pointContextMenu; + QMenu *m_curveContextMenu; + QAction *m_deleteAction; + QAction *m_smoothAction; + QAction *m_cornerAction; + QAction *m_addPoint; + + QScrollArea *m_pointListWidget; + + QList m_segmentProperties; + bool m_block; +}; + +#endif // SPLINEEDITOR_H diff --git a/tools/tools.pro b/tools/tools.pro index 34e90ed816..186c7e9c3b 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -SUBDIRS += qmlscene qmlplugindump qmlmin qmleasing qmlprofiler +SUBDIRS += qmlscene qmlplugindump qmlmin qmleasing qmlprofiler easingcurveeditor contains(QT_CONFIG, qmltest): SUBDIRS += qmltestrunner -- cgit v1.2.3 From b262e81d52e8c269063e1de829aea311dff7c632 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 7 Mar 2012 19:50:23 +0100 Subject: Send accessibility updates for the right item. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Child 0 means the first child. The index needs to be -1 which the default ctor does. Change-Id: I71fbdf5a15dd4593178cb250f06d42f601e40d4d Reviewed-by: Jan-Arve Sæther --- src/quick/items/qquickaccessibleattached.cpp | 2 +- src/quick/items/qquickaccessibleattached_p.h | 4 ++-- src/quick/items/qquickitem.cpp | 4 ++-- src/quick/items/qquicktextinput.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 1e07d96690..20082e8002 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -144,7 +144,7 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) // Enable accessibility for items with accessible content. This also // enables accessibility for the ancestors of souch items. item->d_func()->setAccessibleFlagAndListener(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::ObjectCreated, item, 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::ObjectCreated, item)); } QQuickAccessibleAttached::~QQuickAccessibleAttached() diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 5eea44b6e4..4fc6d90bd8 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -85,7 +85,7 @@ public: if (name != m_name) { m_name = name; emit nameChanged(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, parent(), 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, parent())); } } @@ -95,7 +95,7 @@ public: if (m_description != description) { m_description = description; emit descriptionChanged(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::DescriptionChanged, parent(), 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::DescriptionChanged, parent())); } } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index f2ec0d64cb..8f9a060329 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3018,7 +3018,7 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) void QQuickItem::focusInEvent(QFocusEvent *) { - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this)); } void QQuickItem::focusOutEvent(QFocusEvent *) @@ -3984,7 +3984,7 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible); if (isAccessible) - QAccessible::updateAccessibility(QAccessibleEvent(effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide, q, 0)); + QAccessible::updateAccessibility(QAccessibleEvent(effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide, q)); emit q->visibleChanged(); if (childVisibilityChanged) diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index a06c174e7c..3b62e99557 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -3265,7 +3265,7 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e Q_UNUSED(changed) #else if (changed) - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextUpdated, q, 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextUpdated, q)); #endif } @@ -3891,7 +3891,7 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged() } #ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextCaretMoved, q, 0)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextCaretMoved, q)); #endif return true; -- cgit v1.2.3 From ada9dd41c83aad3890b8f01a98fdbeae04528eba Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Thu, 8 Mar 2012 11:27:04 +1000 Subject: Implement mouseDrag Simulates the drag behavior by press-move-move-release mouse events, we need 2 move events here to trigger the drag threshold. Task-number: QTBUG-22753 Change-Id: Ic3470c061834b7410c524029d82375cba62afa36 Reviewed-by: Michael Brasser --- src/imports/testlib/TestCase.qml | 16 ++++++++ src/imports/testlib/main.cpp | 7 ++++ tests/auto/qmltest/events/tst_drag.qml | 74 ++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 tests/auto/qmltest/events/tst_drag.qml diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 0433483cfd..1f9de5e998 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -407,6 +407,22 @@ Item { qtest_fail("window not shown", 2) } + function mouseDrag(item, x, y, dx, dy, button, modifiers, delay) { + if (item.x === undefined || item.y === undefined) + return + if (button === undefined) + button = Qt.LeftButton + if (modifiers === undefined) + modifiers = Qt.NoModifier + if (delay == undefined) + delay = -1 + + mousePress(item, x, y, button, modifiers, delay) + //trigger draging + mouseMove(item, x + util.dragThreshold + 1, y + util.dragThreshold + 1, delay, button) + mouseMove(item, x + dx, y + dy, delay, button) + } + function mouseClick(item, x, y, button, modifiers, delay) { if (button === undefined) button = Qt.LeftButton diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index 6473d216c7..18039e7a3f 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -48,6 +48,8 @@ #include "private/qtestoptions_p.h" #include "QtQuick/qquickitem.h" #include +#include +#include QML_DECLARE_TYPE(QuickTestResult) QML_DECLARE_TYPE(QuickTestEvent) @@ -61,6 +63,7 @@ class QuickTestUtil : public QObject Q_OBJECT Q_PROPERTY(bool printAvailableFunctions READ printAvailableFunctions NOTIFY printAvailableFunctionsChanged) Q_PROPERTY(bool wrapper READ wrapper NOTIFY wrapperChanged) + Q_PROPERTY(int dragThreshold READ dragThreshold NOTIFY dragThresholdChanged) public: QuickTestUtil(QObject *parent = 0) :QObject(parent) @@ -76,9 +79,13 @@ public: { return true; } + int dragThreshold() const { return qApp->styleHints()->startDragDistance(); } + Q_SIGNALS: void printAvailableFunctionsChanged(); void wrapperChanged(); + void dragThresholdChanged(); + public Q_SLOTS: QQmlV8Handle typeName(const QVariant& v) const diff --git a/tests/auto/qmltest/events/tst_drag.qml b/tests/auto/qmltest/events/tst_drag.qml new file mode 100644 index 0000000000..34b9685e1c --- /dev/null +++ b/tests/auto/qmltest/events/tst_drag.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Rectangle{ + id: root + width:200 + height:200 + + Rectangle { + id:container + width:20 + height:20 + color: "blue" + MouseArea { + id:mouseArea; anchors.fill : parent + drag.maximumX: 180 + drag.maximumY: 180 + drag.minimumX: 0 + drag.minimumY: 0 + drag.target: parent + } + } + + TestCase { + name:"mouserelease" + when:windowShown + function test_mouseDrag() { + mouseDrag(container, 10, 10, 20, 30); + compare(container.x, 20); + compare(container.y, 30); + } + } +} \ No newline at end of file -- cgit v1.2.3 From c291efff26c13963cf98c127bfa759f89f103e48 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Thu, 1 Mar 2012 18:05:16 +0100 Subject: Remove the usage of deprecated qdoc macros. QDoc now has support for Doxygen style commands for italics, bold and list items. This change applies that change in QDoc to the actual documentation. Task-number: QTBUG-24578 Change-Id: I62d203f21df63a95ee236e578b10418fd9680707 Reviewed-by: Jerome Pasion --- doc/src/examples/advtutorial.qdoc | 36 +-- doc/src/examples/dynamicview-tutorial.qdoc | 8 +- doc/src/examples/example-slideswitch.qdoc | 20 +- doc/src/examples/examples.qdoc | 142 +++++------ doc/src/examples/tutorial.qdoc | 32 +-- doc/src/localstorage/localstorage.qdoc | 46 ++-- doc/src/qml/basictypes.qdoc | 36 +-- doc/src/qml/c++models.qdoc | 32 +-- doc/src/qml/codingconventions.qdoc | 22 +- doc/src/qml/dynamicobjects.qdoc | 18 +- doc/src/qml/extending-tutorial.qdoc | 46 ++-- doc/src/qml/integrating.qdoc | 6 +- doc/src/qml/javascriptblocks.qdoc | 32 +-- doc/src/qml/modules.qdoc | 46 ++-- doc/src/qml/network.qdoc | 86 +++---- doc/src/qml/performance.qdoc | 28 +- doc/src/qml/propertybinding.qdoc | 24 +- doc/src/qml/qmlcomponents.qdoc | 18 +- doc/src/qml/qmldate.qdoc | 92 +++---- doc/src/qml/qmldocument.qdoc | 24 +- doc/src/qml/qmlengine.qdoc | 50 ++-- doc/src/qml/qmlevents.qdoc | 6 +- doc/src/qml/qmli18n.qdoc | 4 +- doc/src/qml/qmlintro.qdoc | 24 +- doc/src/qml/qmlnumber.qdoc | 10 +- doc/src/qml/qmlplugins.qdoc | 18 +- doc/src/qml/qmlruntime.qdoc | 4 +- doc/src/qml/qmlsyntax.qdoc | 10 +- doc/src/qml/qmltypes.qdoc | 52 ++-- doc/src/qml/qmlviewer.qdoc | 22 +- doc/src/qml/qtbinding.qdoc | 154 +++++------ doc/src/qml/qtdeclarative.qdoc | 4 +- doc/src/qml/qtjavascript.qdoc | 2 +- doc/src/qml/qtprogrammers.qdoc | 26 +- doc/src/qml/scope.qdoc | 2 +- doc/src/qml/security.qdoc | 16 +- doc/src/qtdeclarative.qdoc | 76 +++--- doc/src/qtquick2/anchor-layout.qdoc | 16 +- doc/src/qtquick2/animation.qdoc | 52 ++-- doc/src/qtquick2/basicelements.qdoc | 20 +- doc/src/qtquick2/behaviors-and-states.qdoc | 4 +- doc/src/qtquick2/canvaspainting.qdoc | 4 +- doc/src/qtquick2/elements.qdoc | 176 ++++++------- doc/src/qtquick2/focus.qdoc | 22 +- doc/src/qtquick2/modelview.qdoc | 50 ++-- doc/src/qtquick2/mouseevents.qdoc | 22 +- doc/src/qtquick2/positioners.qdoc | 8 +- doc/src/qtquick2/qmltexthandling.qdoc | 12 +- doc/src/qtquick2/qtquick-intro.qdoc | 16 +- doc/src/qtquick2/states.qdoc | 46 ++-- doc/src/qtquick2/writingcomponents.qdoc | 52 ++-- doc/src/whatsnew.qdoc | 14 +- .../folderlistmodel/qquickfolderlistmodel.cpp | 44 ++-- src/imports/localstorage/plugin.cpp | 46 ++-- src/imports/testlib/testcase.qdoc | 4 +- src/imports/xmllistmodel/qqmlxmllistmodel.cpp | 8 +- src/qml/qml/qqmlcomponent.cpp | 22 +- src/qml/qml/qqmlcontext.cpp | 2 +- src/qml/qml/qqmlengine.cpp | 46 ++-- src/qml/qml/qqmlextensionplugin.cpp | 6 +- src/qml/qml/qqmlimageprovider.cpp | 6 +- src/qml/qml/qqmlimport.cpp | 18 +- src/qml/qml/qqmlincubator.cpp | 6 +- src/qml/qml/qqmllocale.cpp | 28 +- src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp | 4 +- src/qml/qml/qqmltypeloader.cpp | 22 +- src/qml/qml/qquickworkerscript.cpp | 6 +- src/qml/qml/v8/qjsengine.cpp | 2 +- src/qml/qml/v8/qjsvalue.cpp | 44 ++-- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 80 +++--- src/qml/util/qqmlpropertymap.cpp | 4 +- src/quick/items/context2d/qquickcanvasitem.cpp | 20 +- src/quick/items/context2d/qquickcontext2d.cpp | 168 ++++++------ src/quick/items/qquickaccessibleattached.cpp | 24 +- src/quick/items/qquickanimatedimage.cpp | 2 +- src/quick/items/qquickborderimage.cpp | 22 +- src/quick/items/qquickdrag.cpp | 8 +- src/quick/items/qquickdroparea.cpp | 8 +- src/quick/items/qquickevents.cpp | 54 ++-- src/quick/items/qquickflickable.cpp | 14 +- src/quick/items/qquickgridview.cpp | 54 ++-- src/quick/items/qquickimage.cpp | 54 ++-- src/quick/items/qquickitem.cpp | 90 +++---- src/quick/items/qquickitemanimation.cpp | 10 +- src/quick/items/qquickitemviewtransition.cpp | 62 ++--- src/quick/items/qquicklistview.cpp | 62 ++--- src/quick/items/qquickloader.cpp | 52 ++-- src/quick/items/qquickmousearea.cpp | 24 +- src/quick/items/qquickmultipointtoucharea.cpp | 12 +- src/quick/items/qquickpathview.cpp | 6 +- src/quick/items/qquickpincharea.cpp | 40 +-- src/quick/items/qquickpositioners.cpp | 52 ++-- src/quick/items/qquickrepeater.cpp | 16 +- src/quick/items/qquickshadereffect.cpp | 38 +-- src/quick/items/qquickshadereffectmesh.cpp | 4 +- src/quick/items/qquickshadereffectsource.cpp | 24 +- src/quick/items/qquicktext.cpp | 94 +++---- src/quick/items/qquicktextedit.cpp | 94 +++---- src/quick/items/qquicktextinput.cpp | 86 +++---- src/quick/items/qquickvisualdatamodel.cpp | 12 +- src/quick/particles/qquickimageparticle.cpp | 14 +- src/quick/particles/qquickpointattractor.cpp | 16 +- src/quick/particles/qquickwander.cpp | 6 +- src/quick/scenegraph/coreapi/qsgrendernode.cpp | 34 +-- src/quick/util/qquickanimation.cpp | 282 ++++++++++----------- src/quick/util/qquickconnections.cpp | 6 +- src/quick/util/qquickfontloader.cpp | 14 +- src/quick/util/qquickpath.cpp | 56 ++-- src/quick/util/qquicksmoothedanimation.cpp | 6 +- src/quick/util/qquicksystempalette.cpp | 6 +- src/quick/util/qquicktimeline.cpp | 14 +- tests/auto/shared/testhttpserver.cpp | 12 +- 112 files changed, 1929 insertions(+), 1929 deletions(-) diff --git a/doc/src/examples/advtutorial.qdoc b/doc/src/examples/advtutorial.qdoc index d682a73430..bbb145cd40 100644 --- a/doc/src/examples/advtutorial.qdoc +++ b/doc/src/examples/advtutorial.qdoc @@ -36,7 +36,7 @@ This tutorial walks step-by-step through the creation of a full application usin It assumes that you already know the basics of QML (for example, from reading the \l{QML Tutorial}{simple tutorial}). -In this tutorial we write a game, \i {Same Game}, based on the Same Game application +In this tutorial we write a game, \e {Same Game}, based on the Same Game application included in the declarative \c examples directory, which looks like this: \image declarative-samegame.png @@ -53,10 +53,10 @@ control QML elements. Tutorial chapters: \list 1 -\o \l {declarative/tutorials/samegame/samegame1}{Creating the Game Canvas and Blocks} -\o \l {declarative/tutorials/samegame/samegame2}{Populating the Game Canvas} -\o \l {declarative/tutorials/samegame/samegame3}{Implementing the Game Logic} -\o \l {declarative/tutorials/samegame/samegame4}{Finishing Touches} +\li \l {declarative/tutorials/samegame/samegame1}{Creating the Game Canvas and Blocks} +\li \l {declarative/tutorials/samegame/samegame2}{Populating the Game Canvas} +\li \l {declarative/tutorials/samegame/samegame3}{Implementing the Game Logic} +\li \l {declarative/tutorials/samegame/samegame4}{Finishing Touches} \endlist All the code in this tutorial can be found in Qt's \c examples/declarative/tutorials/samegame @@ -168,18 +168,18 @@ and moves the new block to its position on the game canvas. This involves severa \list -\o \l {QML:Qt::createComponent()}{Qt.createComponent()} is called to +\li \l {QML:Qt::createComponent()}{Qt.createComponent()} is called to generate an element from \c Block.qml. If the component is ready, we can call \c createObject() to create an instance of the \c Block item. -\o If \c createObject() returned null (i.e. if there was an error +\li If \c createObject() returned null (i.e. if there was an error while loading the object), print the error information. -\o Place the block in its position on the board and set its width and +\li Place the block in its position on the board and set its width and height. Also, store it in the blocks array for future reference. -\o Finally, print error information to the console if the component +\li Finally, print error information to the console if the component could not be loaded for some reason (for example, if the file is missing). @@ -228,11 +228,11 @@ until it is won or lost. To do this, we have added the following functions to \c samegame.js: \list -\o \c{handleClick(x,y)} -\o \c{floodFill(xIdx,yIdx,type)} -\o \c{shuffleDown()} -\o \c{victoryCheck()} -\o \c{floodMoveCheck(xIdx, yIdx, type)} +\li \c{handleClick(x,y)} +\li \c{floodFill(xIdx,yIdx,type)} +\li \c{shuffleDown()} +\li \c{victoryCheck()} +\li \c{floodMoveCheck(xIdx, yIdx, type)} \endlist As this is a tutorial about QML, not game design, we will only discuss \c handleClick() and \c victoryCheck() below since they interface directly with the QML elements. Note that although the game logic here is written in JavaScript, it could have been written in C++ and then exposed to QML. @@ -459,10 +459,10 @@ makes it very easy to fetch and display XML based data such as RSS in a QML appl By following this tutorial you've seen how you can write a fully functional application in QML: \list -\o Build your application with \l {{QML Elements}}{QML elements} -\o Add application logic \l{JavaScript Expressions in QML}{with JavaScript code} -\o Add animations with \l {Behavior}{Behaviors} and \l{QML States}{states} -\o Store persistent application data using, for example, the \l{Offline Storage API} or \l XMLHttpRequest +\li Build your application with \l {{QML Elements}}{QML elements} +\li Add application logic \l{JavaScript Expressions in QML}{with JavaScript code} +\li Add animations with \l {Behavior}{Behaviors} and \l{QML States}{states} +\li Store persistent application data using, for example, the \l{Offline Storage API} or \l XMLHttpRequest \endlist There is so much more to learn about QML that we haven't been able to cover in this tutorial. Check out all the diff --git a/doc/src/examples/dynamicview-tutorial.qdoc b/doc/src/examples/dynamicview-tutorial.qdoc index 517dacc2f1..d1f69c28bb 100644 --- a/doc/src/examples/dynamicview-tutorial.qdoc +++ b/doc/src/examples/dynamicview-tutorial.qdoc @@ -39,10 +39,10 @@ data to dynamically sort all items in a view. Tutorial chapters: \list 1 -\o \l {declarative/tutorials/dynamicview/dynamicview1}{A Simple ListView and Delegate} -\o \l {declarative/tutorials/dynamicview/dynamicview2}{Dragging View Items} -\o \l {declarative/tutorials/dynamicview/dynamicview3}{Moving Dragged Items} -\o \l {declarative/tutorials/dynamicview/dynamicview4}{Sorting Items} +\li \l {declarative/tutorials/dynamicview/dynamicview1}{A Simple ListView and Delegate} +\li \l {declarative/tutorials/dynamicview/dynamicview2}{Dragging View Items} +\li \l {declarative/tutorials/dynamicview/dynamicview3}{Moving Dragged Items} +\li \l {declarative/tutorials/dynamicview/dynamicview4}{Sorting Items} \endlist All the code in this tutorial can be found in Qt's \c examples/declarative/tutorials/dynamicview diff --git a/doc/src/examples/example-slideswitch.qdoc b/doc/src/examples/example-slideswitch.qdoc index 689841a78b..25e81861b7 100644 --- a/doc/src/examples/example-slideswitch.qdoc +++ b/doc/src/examples/example-slideswitch.qdoc @@ -37,12 +37,12 @@ The code for this example can be found in the \c examples/declarative/ui-compone The elements that compose the switch are: \list -\o a \c on property (the interface to interact with the switch), -\o two images (the background image and the knob), -\o two mouse regions for user interation (on the background image and on the knob), -\o two states (a \i on state and a \i off state), -\o two functions or slots to react to the user interation (\c toggle() and \c dorelease()), -\o and a transition that describe how to go from one state to the other. +\li a \c on property (the interface to interact with the switch), +\li two images (the background image and the knob), +\li two mouse regions for user interation (on the background image and on the knob), +\li two states (an \e on state and an \e off state), +\li two functions or slots to react to the user interation (\c toggle() and \c dorelease()), +\li and a transition that describe how to go from one state to the other. \endlist \section1 Switch.qml @@ -93,8 +93,8 @@ in the \c dorelease() function that is called in the \c onReleased property. We define the two states of the switch: \list -\o In the \i on state the knob is on the right (\c x position is 78) and the \c on property is \c true. -\o In the \i off state the knob is on the left (\c x position is 1) and the \c on property is \c false. +\li In the \e on state the knob is on the right (\c x position is 78) and the \c on property is \c true. +\li In the \e off state the knob is on the left (\c x position is 1) and the \c on property is \c false. \endlist For more information on states see \l{qmlstates}{QML States}. @@ -106,13 +106,13 @@ We add two JavaScript functions to our switch: \snippet examples/declarative/ui-components/slideswitch/content/Switch.qml 2 This first function is called when the background image or the knob are clicked. We simply want the switch to toggle between the two -states (\i on and \i off). +states (\e on and \e off). \snippet examples/declarative/ui-components/slideswitch/content/Switch.qml 3 This second function is called when the knob is released and we want to make sure that the knob does not end up between states -(neither \i on nor \i off). If it is the case call the \c toggle() function otherwise we do nothing. +(neither \e on nor \e off). If it is the case call the \c toggle() function otherwise we do nothing. For more information on scripts see \l{JavaScript Expressions in QML}. diff --git a/doc/src/examples/examples.qdoc b/doc/src/examples/examples.qdoc index f9c89d87f4..a99dc8c263 100644 --- a/doc/src/examples/examples.qdoc +++ b/doc/src/examples/examples.qdoc @@ -103,10 +103,10 @@ This set of code samples are part of the collection of \l{Qt Examples}. Mouse and Keyboard Input \enddiv \list - \o \l{declarative/text/fonts}{Fonts} - \o \l{declarative/text/textselection}{Text Selection} - \o \l{declarative/keyinteraction/focus}{Keyboard Focus} - \o \l{declarative/touchinteraction/mousearea}{MouseArea} + \li \l{declarative/text/fonts}{Fonts} + \li \l{declarative/text/textselection}{Text Selection} + \li \l{declarative/keyinteraction/focus}{Keyboard Focus} + \li \l{declarative/touchinteraction/mousearea}{MouseArea} \endlist \enddiv \div {class="threecolumn_piece"} @@ -114,10 +114,10 @@ This set of code samples are part of the collection of \l{Qt Examples}. States and Transitions \enddiv \list - \o \l{declarative/animation/states}{States} - \o \l{declarative/animation/basics}{Animation Essentials} - \o \l{declarative/animation/behaviors}{Behaviors} - \o \l{declarative/animation/easing}{Easing} + \li \l{declarative/animation/states}{States} + \li \l{declarative/animation/basics}{Animation Essentials} + \li \l{declarative/animation/behaviors}{Behaviors} + \li \l{declarative/animation/easing}{Easing} \endlist \enddiv \div {class="threecolumn_piece"} @@ -125,14 +125,14 @@ This set of code samples are part of the collection of \l{Qt Examples}. UI Components \enddiv \list - \o \l{declarative/ui-components/dialcontrol}{Dial Control} - \o \l{declarative/ui-components/flipable}{Flipable} - \o \l{declarative/ui-components/progressbar}{Progress Bar} - \o \l{declarative/ui-components/scrollbar}{Scroll Bar} - \o \l{declarative/ui-components/searchbox}{Search Box} - \o \l{declarative/ui-components/slideswitch}{Slide Switch} - \o \l{declarative/ui-components/spinner}{Spinner} - \o \l{declarative/ui-components/tabwidget}{Tab Widget} + \li \l{declarative/ui-components/dialcontrol}{Dial Control} + \li \l{declarative/ui-components/flipable}{Flipable} + \li \l{declarative/ui-components/progressbar}{Progress Bar} + \li \l{declarative/ui-components/scrollbar}{Scroll Bar} + \li \l{declarative/ui-components/searchbox}{Search Box} + \li \l{declarative/ui-components/slideswitch}{Slide Switch} + \li \l{declarative/ui-components/spinner}{Spinner} + \li \l{declarative/ui-components/tabwidget}{Tab Widget} \endlist \enddiv \div {class="threecolumn_piece"} @@ -140,11 +140,11 @@ This set of code samples are part of the collection of \l{Qt Examples}. Positioners and Layout \enddiv \list - \o \l{declarative/positioners}{Row and Column} - \o \l{declarative/righttoleft/layoutmirroring}{Layout Mirroring} - \o \l{declarative/righttoleft/layoutdirection}{Layout Direction} - \o \l{declarative/righttoleft/textalignment}{Text Alignment} - \o \l{declarative/screenorientation}{Screen Orientation} + \li \l{declarative/positioners}{Row and Column} + \li \l{declarative/righttoleft/layoutmirroring}{Layout Mirroring} + \li \l{declarative/righttoleft/layoutdirection}{Layout Direction} + \li \l{declarative/righttoleft/textalignment}{Text Alignment} + \li \l{declarative/screenorientation}{Screen Orientation} \endlist \enddiv \div {class="threecolumn_piece"} @@ -152,15 +152,15 @@ This set of code samples are part of the collection of \l{Qt Examples}. Data with Models and Views \enddiv \list - \o \l{declarative/modelviews/gridview}{GridView} - \o \l{declarative/modelviews/listview}{ListView} - \o \l{declarative/modelviews/pathview}{PathView} - \o \l{declarative/modelviews/package}{Package} - \o \l{declarative/modelviews/visualitemmodel}{VisualItemModel} - \o \l{declarative/modelviews/stringlistmodel}{String ListModel} - \o \l{declarative/modelviews/objectlistmodel}{Object ListModel} - \o \l{declarative/modelviews/abstractitemmodel}{AbstractItemModel} - \o \l{declarative/modelviews/webview}{WebView} + \li \l{declarative/modelviews/gridview}{GridView} + \li \l{declarative/modelviews/listview}{ListView} + \li \l{declarative/modelviews/pathview}{PathView} + \li \l{declarative/modelviews/package}{Package} + \li \l{declarative/modelviews/visualitemmodel}{VisualItemModel} + \li \l{declarative/modelviews/stringlistmodel}{String ListModel} + \li \l{declarative/modelviews/objectlistmodel}{Object ListModel} + \li \l{declarative/modelviews/abstractitemmodel}{AbstractItemModel} + \li \l{declarative/modelviews/webview}{WebView} \endlist \enddiv \div {class="threecolumn_piece"} @@ -168,12 +168,12 @@ This set of code samples are part of the collection of \l{Qt Examples}. Advance UI Components \enddiv \list - \o \l{declarative/modelviews/parallax}{Parallax} - \o \l{declarative/toys/clocks}{Clocks} - \o \l{declarative/toys/corkboards}{Corkboards} - \o \l{declarative/toys/dynamicscene}{Dynamic Scene} - \o \l{declarative/toys/tic-tac-toe}{Tic Tac Toe} - \o \l{declarative/toys/tvtennis}{TV Tennis} + \li \l{declarative/modelviews/parallax}{Parallax} + \li \l{declarative/toys/clocks}{Clocks} + \li \l{declarative/toys/corkboards}{Corkboards} + \li \l{declarative/toys/dynamicscene}{Dynamic Scene} + \li \l{declarative/toys/tic-tac-toe}{Tic Tac Toe} + \li \l{declarative/toys/tvtennis}{TV Tennis} \endlist \enddiv \div {class="threecolumn_piece"} @@ -181,8 +181,8 @@ This set of code samples are part of the collection of \l{Qt Examples}. Image Elements \enddiv \list - \o \l{declarative/imageelements/borderimage}{BorderImage} - \o \l{declarative/imageelements/image}{Image} + \li \l{declarative/imageelements/borderimage}{BorderImage} + \li \l{declarative/imageelements/image}{Image} \endlist \enddiv \div {class="threecolumn_piece"} @@ -190,8 +190,8 @@ This set of code samples are part of the collection of \l{Qt Examples}. Loading Resources \enddiv \list - \o \l{declarative/sqllocalstorage}{SQL Local Storage} - \o \l{declarative/xml/xmlhttprequest}{XmlHttpRequest} + \li \l{declarative/sqllocalstorage}{SQL Local Storage} + \li \l{declarative/xml/xmlhttprequest}{XmlHttpRequest} \endlist \enddiv \div {class="threecolumn_piece"} @@ -199,7 +199,7 @@ This set of code samples are part of the collection of \l{Qt Examples}. Localization \enddiv \list - \o \l{declarative/i18n}{Translation} + \li \l{declarative/i18n}{Translation} \endlist \enddiv \div {class="threecolumn_piece"} @@ -207,8 +207,8 @@ This set of code samples are part of the collection of \l{Qt Examples}. Threading \enddiv \list - \o \l{declarative/threading/threadedlistmodel}{Threaded ListModel} - \o \l{declarative/threading/workerscript}{WorkerScript Element} + \li \l{declarative/threading/threadedlistmodel}{Threaded ListModel} + \li \l{declarative/threading/workerscript}{WorkerScript Element} \endlist \enddiv \div {class="threecolumn_piece"} @@ -216,7 +216,7 @@ This set of code samples are part of the collection of \l{Qt Examples}. Graphical Effects \enddiv \list - \o \l{declarative/shadereffects}{Shader Effects} + \li \l{declarative/shadereffects}{Shader Effects} \endlist \enddiv \enddiv @@ -231,16 +231,16 @@ This set of code samples are part of the collection of \l{Qt Examples}. From Qt C++ to QML \enddiv \list - \o \l {declarative/cppextensions/referenceexamples/adding}{Exporting C++ Classes} - \o \l {declarative/cppextensions/referenceexamples/properties}{Exporting Qt C++ Properties} - \o \l {declarative/cppextensions/referenceexamples/coercion}{C++ Inheritance and Coercion} - \o \l {declarative/cppextensions/referenceexamples/default}{Default Property} - \o \l {declarative/cppextensions/referenceexamples/grouped}{Grouped Properties} - \o \l {declarative/cppextensions/referenceexamples/attached}{Attached Properties} - \o \l {declarative/cppextensions/referenceexamples/signal}{Signal Support} - \o \l {declarative/cppextensions/referenceexamples/methods}{Methods Support} - \o \l {declarative/cppextensions/referenceexamples/valuesource}{Property Value Source} - \o \l {declarative/cppextensions/referenceexamples/binding}{Binding} + \li \l {declarative/cppextensions/referenceexamples/adding}{Exporting C++ Classes} + \li \l {declarative/cppextensions/referenceexamples/properties}{Exporting Qt C++ Properties} + \li \l {declarative/cppextensions/referenceexamples/coercion}{C++ Inheritance and Coercion} + \li \l {declarative/cppextensions/referenceexamples/default}{Default Property} + \li \l {declarative/cppextensions/referenceexamples/grouped}{Grouped Properties} + \li \l {declarative/cppextensions/referenceexamples/attached}{Attached Properties} + \li \l {declarative/cppextensions/referenceexamples/signal}{Signal Support} + \li \l {declarative/cppextensions/referenceexamples/methods}{Methods Support} + \li \l {declarative/cppextensions/referenceexamples/valuesource}{Property Value Source} + \li \l {declarative/cppextensions/referenceexamples/binding}{Binding} \endlist \enddiv \div {class="threecolumn_piece"} @@ -248,10 +248,10 @@ This set of code samples are part of the collection of \l{Qt Examples}. Plugins and Resources \enddiv \list - \o \l{declarative/cppextensions/plugins}{Plugins} - \o \l{declarative/cppextensions/imageprovider}{Image Provider} - \o \l{declarative/cppextensions/networkaccessmanagerfactory}{Network Access Manager} - \o \l{src/imports/folderlistmodel}{Folder List Model} - a C++ model plugin + \li \l{declarative/cppextensions/plugins}{Plugins} + \li \l{declarative/cppextensions/imageprovider}{Image Provider} + \li \l{declarative/cppextensions/networkaccessmanagerfactory}{Network Access Manager} + \li \l{src/imports/folderlistmodel}{Folder List Model} - a C++ model plugin \endlist \enddiv \div {class="threecolumn_piece"} @@ -259,8 +259,8 @@ This set of code samples are part of the collection of \l{Qt Examples}. Qt UI and QML Integration \enddiv \list - \o \l{declarative-cppextensions-qgraphicslayouts.html}{QGraphicsLayouts} - \o \l{declarative/cppextensions/qwidgets}{QWidgets} + \li \l{declarative-cppextensions-qgraphicslayouts.html}{QGraphicsLayouts} + \li \l{declarative/cppextensions/qwidgets}{QWidgets} \endlist \enddiv \enddiv @@ -276,11 +276,11 @@ This set of code samples are part of the collection of \l{Qt Examples}. Elements and Components \enddiv \list - \o \l{QML Elements} - \o \l{external: Qt Mobility QML Plugins}{QML Plugins} - \o \l{external: Qt Quick Components for Symbian}{Symbian Components} - \o MeeGo Components - \o \l{QtWebKit QML Module} + \li \l{QML Elements} + \li \l{external: Qt Mobility QML Plugins}{QML Plugins} + \li \l{external: Qt Quick Components for Symbian}{Symbian Components} + \li MeeGo Components + \li \l{QtWebKit QML Module} \endlist \enddiv \div {class="threecolumn_piece"} @@ -288,9 +288,9 @@ This set of code samples are part of the collection of \l{Qt Examples}. Qt Developer Network \enddiv \list - \o \l{Qt eLearning}{Training Materials} - \o \l{Forums on Qt Developer Network}{Forums} - \o \l{Wiki on Qt Developer Network}{Wiki} + \li \l{Qt eLearning}{Training Materials} + \li \l{Forums on Qt Developer Network}{Forums} + \li \l{Wiki on Qt Developer Network}{Wiki} \endlist \enddiv \div {class="threecolumn_piece"} @@ -298,9 +298,9 @@ This set of code samples are part of the collection of \l{Qt Examples}. Reference \enddiv \list - \o \l{All Classes}{Qt API} - \o \l{external: Qt Creator Manual}{Qt Creator Manual} - \o \l{Develop with Qt} + \li \l{All Classes}{Qt API} + \li \l{external: Qt Creator Manual}{Qt Creator Manual} + \li \l{Develop with Qt} \endlist \enddiv \enddiv diff --git a/doc/src/examples/tutorial.qdoc b/doc/src/examples/tutorial.qdoc index 9042b5e3d8..d8d6e14f09 100644 --- a/doc/src/examples/tutorial.qdoc +++ b/doc/src/examples/tutorial.qdoc @@ -46,9 +46,9 @@ The tutorial's source code is located in the $QTDIR/examples/declarative/tutoria Tutorial chapters: \list 1 -\o \l {QML Tutorial 1 - Basic Types}{Basic Types} -\o \l {QML Tutorial 2 - QML Components}{QML Components} -\o \l {QML Tutorial 3 - States and Transitions}{States and Transitions} +\li \l {QML Tutorial 1 - Basic Types}{Basic Types} +\li \l {QML Tutorial 2 - QML Components}{QML Components} +\li \l {QML Tutorial 3 - States and Transitions}{States and Transitions} \endlist */ @@ -97,7 +97,7 @@ We add a \l Text element as a child of the root Rectangle element that displays The \c y property is used to position the text vertically at 30 pixels from the top of its parent. The \c anchors.horizontalCenter property refers to the horizontal center of an element. -In this case, we specify that our text element should be horizontally centered in the \i page element (see \l{anchor-layout}{Anchor-Based Layout}). +In this case, we specify that our text element should be horizontally centered in the \e page element (see \l{anchor-layout}{Anchor-Based Layout}). The \c font.pointSize and \c font.bold properties are related to fonts and use the \l{dot properties}{dot notation}. @@ -141,24 +141,24 @@ Here is the QML code for \c Cell.qml: \snippet examples/declarative/tutorials/helloworld/Cell.qml 1 -The root element of our component is an \l Item with the \c id \i container. +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/Cell.qml 4 -We declare a \c cellColor property. This property is accessible from \i outside our component, this allows us +We declare a \c cellColor 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{Property Binding in QML}). \snippet examples/declarative/tutorials/helloworld/Cell.qml 5 -We want our component to also have a signal that we call \i clicked with a \i cellColor parameter of type \i color. +We want our component to also have a signal that we call \e clicked with a \e cellColor parameter of type \e color. We will use this signal to change the color of the text in the main QML file later. \snippet examples/declarative/tutorials/helloworld/Cell.qml 2 -Our cell component is basically a colored rectangle with the \c id \i rectangle. +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}). @@ -168,8 +168,8 @@ In this case the rectangle will have the same size as its parent (see \l{anchor- In order to change the color of the text when clicking on a cell, we create a \l MouseArea element with the same size as its parent. -A \l MouseArea defines a signal called \i clicked. -When this signal is triggered we want to emit our own \i clicked signal with the color as parameter. +A \l MouseArea defines a signal called \e clicked. +When this signal is triggered we want to emit our own \e clicked signal with the color as parameter. \section2 The main QML file @@ -181,8 +181,8 @@ We create the color picker by putting 6 cells with different colors in a grid. \snippet examples/declarative/tutorials/helloworld/tutorial2.qml 1 -When the \i clicked signal of our cell is triggered, we want to set the color of the text to the \i cellColor passed as a parameter. -We can react to any signal of our component through a property of the name \i 'onSignalName' (see \l{Signal Handlers}). +When the \e clicked signal of our cell is triggered, we want to set the color of the text to the \e cellColor 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}). */ /*! @@ -206,10 +206,10 @@ Here is the QML code: \snippet examples/declarative/tutorials/helloworld/tutorial3.qml 2 -First, we create a new \i down state for our text element. +First, we create a new \e down state for our text element. This state will be activated when the \l MouseArea is pressed, and deactivated when it is released. -The \i down state includes a set of property changes from our implicit \i {default state} +The \e down state includes a set of property changes from our implicit \e {default state} (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. @@ -219,9 +219,9 @@ Because we don't want the text to appear at the bottom instantly but rather move we add a transition between our two states. \c from and \c to define the states between which the transition will run. -In this case, we want a transition from the default state to our \i down state. +In this case, we want a transition from the default state to our \li down state. -Because we want the same transition to be run in reverse when changing back from the \i down state to the default state, +Because we want the same transition to be run in reverse when changing back from the \e down state to the default state, we set \c reversible to \c true. This is equivalent to writing the two transitions separately. diff --git a/doc/src/localstorage/localstorage.qdoc b/doc/src/localstorage/localstorage.qdoc index 5287120e86..596dbf700e 100644 --- a/doc/src/localstorage/localstorage.qdoc +++ b/doc/src/localstorage/localstorage.qdoc @@ -74,9 +74,9 @@ using the Local Storage API. \section3 db = openDatabaseSync(identifier, version, description, estimated_size, callback(db)) -Returns the database identified by \i identifier. If the database does not already exist, it -is created, and the function \i callback is called with the database as a parameter. \i description -and \i estimated_size are written to the INI file (described below), but are otherwise currently +Returns the database identified by \e identifier. If the database does not already exist, it +is created, and the function \e callback is called with the database as a parameter. \e description +and \e estimated_size are written to the INI file (described below), but are otherwise currently unused. May throw exception with code property SQLException.DATABASE_ERR, or SQLException.VERSION_ERR. @@ -84,51 +84,51 @@ May throw exception with code property SQLException.DATABASE_ERR, or SQLExceptio When a database is first created, an INI file is also created specifying its characteristics: \table -\header \o \bold {Key} \o \bold {Value} -\row \o Name \o The name of the database passed to \c openDatabase() -\row \o Version \o The version of the database passed to \c openDatabase() -\row \o Description \o The description of the database passed to \c openDatabase() -\row \o EstimatedSize \o The estimated size (in bytes) of the database passed to \c openDatabase() -\row \o Driver \o Currently "QSQLITE" +\header \li \b {Key} \li \b {Value} +\row \li Name \li The name of the database passed to \c openDatabase() +\row \li Version \li The version of the database passed to \c openDatabase() +\row \li Description \li The description of the database passed to \c openDatabase() +\row \li EstimatedSize \li The estimated size (in bytes) of the database passed to \c openDatabase() +\row \li Driver \li Currently "QSQLITE" \endtable This data can be used by application tools. \section3 db.changeVersion(from, to, callback(tx)) -This method allows you to perform a \i{Scheme Upgrade}. +This method allows you to perform a \e{Scheme Upgrade}. -If the current version of \i db is not \i from, then an exception is thrown. +If the current version of \e db is not \e from, then an exception is thrown. -Otherwise, a database transaction is created and passed to \i callback. In this function, -you can call \i executeSql on \i tx to upgrade the database. +Otherwise, a database transaction is created and passed to \e callback. In this function, +you can call \e executeSql on \e tx to upgrade the database. May throw exception with code property SQLException.DATABASE_ERR or SQLException.UNKNOWN_ERR. \section3 db.transaction(callback(tx)) -This method creates a read/write transaction and passed to \i callback. In this function, -you can call \i executeSql on \i tx to read and modify the database. +This method creates a read/write transaction and passed to \e callback. In this function, +you can call \e executeSql on \e tx to read and modify the database. If the callback throws exceptions, the transaction is rolled back. \section3 db.readTransaction(callback(tx)) -This method creates a read-only transaction and passed to \i callback. In this function, -you can call \i executeSql on \i tx to read the database (with SELECT statements). +This method creates a read-only transaction and passed to \e callback. In this function, +you can call \e executeSql on \e tx to read the database (with SELECT statements). \section3 results = tx.executeSql(statement, values) -This method executes a SQL \i statement, binding the list of \i values to SQL positional parameters ("?"). +This method executes a SQL \e statement, binding the list of \e values to SQL positional parameters ("?"). It returns a results object, with the following properties: \table -\header \o \bold {Type} \o \bold {Property} \o \bold {Value} \o \bold {Applicability} -\row \o int \o rows.length \o The number of rows in the result \o SELECT -\row \o var \o rows.item(i) \o Function that returns row \i i of the result \o SELECT -\row \o int \o rowsAffected \o The number of rows affected by a modification \o UPDATE, DELETE -\row \o string \o insertId \o The id of the row inserted \o INSERT +\header \li \b {Type} \li \b {Property} \li \b {Value} \li \b {Applicability} +\row \li int \li rows.length \li The number of rows in the result \li SELECT +\row \li var \li rows.item(i) \li Function that returns row \e i of the result \li SELECT +\row \li int \li rowsAffected \li The number of rows affected by a modification \li UPDATE, DELETE +\row \li string \li insertId \li The id of the row inserted \li INSERT \endtable May throw exception with code property SQLException.DATABASE_ERR, SQLException.SYNTAX_ERR, or SQLException.UNKNOWN_ERR. diff --git a/doc/src/qml/basictypes.qdoc b/doc/src/qml/basictypes.qdoc index 317dd54443..517bc953ea 100644 --- a/doc/src/qml/basictypes.qdoc +++ b/doc/src/qml/basictypes.qdoc @@ -88,7 +88,7 @@ Item { width: 100.45; height: 150.82 } \endqml - \bold{Note:} In QML all reals are stored in double precision, \l + \b{Note:} In QML all reals are stored in double precision, \l {http://en.wikipedia.org/wiki/IEEE_754} {IEEE floating point} format. @@ -331,12 +331,12 @@ A font type has the properties of a QFont. The properties are: \list - \o \c string font.family - \o \c bool font.bold - \o \c bool font.italic - \o \c bool font.underline - \o \c real font.pointSize - \o \c int font.pixelSize + \li \c string font.family + \li \c bool font.bold + \li \c bool font.italic + \li \c bool font.underline + \li \c real font.pointSize + \li \c int font.pixelSize \endlist Example: @@ -357,9 +357,9 @@ are: \list - \o \c slot action.trigger - invoke the action - \o \c bool action.enabled - true if the action is enabled - \o \c string action.text - the text associated with the action + \li \c slot action.trigger - invoke the action + \li \c bool action.enabled - true if the action is enabled + \li \c string action.text - the text associated with the action \endlist Actions are used like this: @@ -462,7 +462,7 @@ array containing a single function element instead. It is important to note that changes in regular properties of JavaScript - objects assigned to a var property will \bold{not} trigger updates of bindings + objects assigned to a var property will \b{not} trigger updates of bindings that access them. The example below will display "The car has 4 wheels" as the change to the wheels property will not cause the reevaluation of the binding assigned to the "text" property: @@ -536,8 +536,8 @@ Finally, the \c variant type can also hold: \list - \o An array of \l {QML Basic Types}{basic type} values - \o A map of key-value pairs with \l {QML Basic Types}{basic-type} values + \li An array of \l {QML Basic Types}{basic type} values + \li A map of key-value pairs with \l {QML Basic Types}{basic-type} values \endlist For example, below is an \c items array and an \c attributes map. Their @@ -561,12 +561,12 @@ \endqml While this is a convenient way to store array and map-type values, you - must be aware that the \c items and \c attributes properties above are \i not + must be aware that the \c items and \c attributes properties above are \e not QML objects (and certainly not JavaScript object either) and the key-value - pairs in \c attributes are \i not QML properties. Rather, the \c items + pairs in \c attributes are \e not QML properties. Rather, the \c items property holds an array of values, and \c attributes holds a set of key-value pairs. Since they are stored as a set of values, instead of as an object, - their contents \i cannot be modified individually: + their contents \e cannot be modified individually: \qml Item { @@ -592,7 +592,7 @@ One way to "update" the contents of an array or map is to copy the property to a JavaScript object, modify the copy as desired, and then reassign the property to the updated copy. Note, however, that this is not efficient. - In the example below, which reassigns the \c attributes property, the \i entire + In the example below, which reassigns the \c attributes property, the \e entire set of key-value pairs must be serialized and deserialized every time it is copied between a JavaScript object and a QML property: @@ -615,7 +615,7 @@ within a JavaScript file. JavaScript programmers should also note that when a JavaScript object is - copied to an array or map property, the \i contents of the object (that is, + copied to an array or map property, the \e contents of the object (that is, its key-value properties) are copied, rather than the object itself. The property does not hold a reference to the original JavaScript object, and extra data such as the object's JavaScript prototype chain is also lost in diff --git a/doc/src/qml/c++models.qdoc b/doc/src/qml/c++models.qdoc index 943c79c184..e2f2f32b5c 100644 --- a/doc/src/qml/c++models.qdoc +++ b/doc/src/qml/c++models.qdoc @@ -41,7 +41,7 @@ models. \section1 QStringList-based Model A model may be a simple \l QStringList, which provides the contents of the list - via the \i modelData role. + via the \e modelData role. Here is a ListView with a delegate that references its model item's value using the \c modelData role: @@ -55,7 +55,7 @@ models. The complete example is available in Qt's \l {declarative/modelviews/stringlistmodel}{examples/declarative/modelviews/stringlistmodel} directory. - \bold{Note:} There is no way for the view to know that the contents of a QStringList + \b{Note:} There is no way for the view to know that the contents of a QStringList have changed. If the QStringList changes, it will be necessary to reset the model by calling QQmlContext::setContextProperty() again. @@ -107,18 +107,18 @@ models. \table \header - \o Qt Role - \o QML Role Name + \li Qt Role + \li QML Role Name \row - \o Qt::DisplayRole - \o display + \li Qt::DisplayRole + \li display \row - \o Qt::DecorationRole - \o decoration + \li Qt::DecorationRole + \li decoration \endtable Here is an application with a QAbstractListModel subclass named \c AnimalModel - that has \i type and \i size roles. It calls QAbstractItemModel::setRoleNames() to set the + that has \e type and \e size roles. It calls QAbstractItemModel::setRoleNames() to set the role names for accessing the properties via QML: \snippet examples/declarative/modelviews/abstractitemmodel/model.h 0 @@ -132,7 +132,7 @@ models. \snippet examples/declarative/modelviews/abstractitemmodel/main.cpp 0 \dots - This model is displayed by a ListView delegate that accesses the \i type and \i size + This model is displayed by a ListView delegate that accesses the \e type and \e size roles: \snippet examples/declarative/modelviews/abstractitemmodel/view.qml 0 @@ -152,10 +152,10 @@ models. with models of type QAbstractItemModel: \list - \o \i hasModelChildren role property to determine whether a node has child nodes. - \o \l VisualDataModel::rootIndex allows the root node to be specified - \o \l VisualDataModel::modelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex - \o \l VisualDataModel::parentModelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex + \li \e hasModelChildren role property to determine whether a node has child nodes. + \li \l VisualDataModel::rootIndex allows the root node to be specified + \li \l VisualDataModel::modelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex + \li \l VisualDataModel::parentModelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex \endlist \section1 Exposing C++ Data Models to QML @@ -169,7 +169,7 @@ created directly as elements within QML: \table \row -\o +\li \code class MyModelPlugin : public QQmlExtensionPlugin { @@ -184,7 +184,7 @@ public: Q_EXPORT_PLUGIN2(mymodelplugin, MyModelPlugin); \endcode -\o +\li \qml MyModel { id: myModel diff --git a/doc/src/qml/codingconventions.qdoc b/doc/src/qml/codingconventions.qdoc index 9e1ce34c2c..92d8ee112a 100644 --- a/doc/src/qml/codingconventions.qdoc +++ b/doc/src/qml/codingconventions.qdoc @@ -37,20 +37,20 @@ This document contains the QML coding conventions that we follow in our document Through our documentation and examples, QML objects are always structured in the following order: \list -\o id -\o property declarations -\o signal declarations -\o JavaScript functions -\o object properties -\o child objects -\o states -\o transitions +\li id +\li property declarations +\li signal declarations +\li JavaScript functions +\li object properties +\li child objects +\li states +\li transitions \endlist For better readability, we separate these different parts with an empty line. -For example, a hypothetical \i photo QML object would look like this: +For example, a hypothetical \e photo QML object would look like this: \snippet doc/src/snippets/qml/codingconventions/photo.qml 0 @@ -58,7 +58,7 @@ For example, a hypothetical \i photo QML object would look like this: \section1 Grouped Properties If using multiple properties from a group of properties, -we use the \i {group notation} rather than the \i {dot notation} to improve readability. +we use the \e {group notation} rather than the \e {dot notation} to improve readability. For example, this: @@ -74,7 +74,7 @@ can be written like this: QML and JavaScript do not enforce private properties like C++. There is a need to hide these private properties, for example, when the properties are part of the implementation. As a convention, private properties begin with two -\i underscore characters. For example, \c __area, is a property that is +\e underscore characters. For example, \c __area, is a property that is accessible but is not meant for public use. Note that QML and JavaScript will grant the user access to these properties. diff --git a/doc/src/qml/dynamicobjects.qdoc b/doc/src/qml/dynamicobjects.qdoc index c50f9dd337..2886d5b28a 100644 --- a/doc/src/qml/dynamicobjects.qdoc +++ b/doc/src/qml/dynamicobjects.qdoc @@ -68,10 +68,10 @@ a \l Component object from this URL. Once you have a \l Component, you can call its \l {Component::createObject()}{createObject()} method to create an instance of the component. This function can take one or two arguments: \list -\o The first is the parent for the new item. Since graphical items will not appear on the scene without a parent, it is +\li The first is the parent for the new item. Since graphical items will not appear on the scene without a parent, it is recommended that you set the parent this way. However, if you wish to set the parent later you can safely pass \c null to this function. -\o The second is optional and is a map of property-value items that define initial any property values for the item. +\li The second is optional and is a map of property-value items that define initial any property values for the item. Property values specified by this argument are applied to the object before its creation is finalized, avoiding binding errors that may occur if particular properties must be initialized to enable other property bindings. when certain properties have been bound to before they have been set by the code. Additionally, there are small @@ -144,11 +144,11 @@ the bindings in the dynamic item will no longer work. The actual creation context depends on how an item is created: \list -\o If \l {QML:Qt::createComponent()}{Qt.createComponent()} is used, the creation context +\li If \l {QML:Qt::createComponent()}{Qt.createComponent()} is used, the creation context is the QQmlContext in which this method is called -\o If \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()} +\li If \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()} if called, the creation context is the context of the parent item passed to this method -\o If a \c {Component{}} item is defined and \l {Component::createObject()}{createObject()} +\li If a \c {Component{}} item is defined and \l {Component::createObject()}{createObject()} is called on that item, the creation context is the context in which the \c Component is defined \endlist @@ -177,12 +177,12 @@ component. Each instance runs a NumberAnimation, and when the animation has fini \table \row -\o \c application.qml -\o \c SelfDestroyingRect.qml +\li \c application.qml +\li \c SelfDestroyingRect.qml \row -\o \snippet doc/src/snippets/qml/dynamicObjects-destroy.qml 0 -\o \snippet doc/src/snippets/qml/SelfDestroyingRect.qml 0 +\li \snippet doc/src/snippets/qml/dynamicObjects-destroy.qml 0 +\li \snippet doc/src/snippets/qml/SelfDestroyingRect.qml 0 \endtable diff --git a/doc/src/qml/extending-tutorial.qdoc b/doc/src/qml/extending-tutorial.qdoc index b995c32cca..a17cd24cac 100644 --- a/doc/src/qml/extending-tutorial.qdoc +++ b/doc/src/qml/extending-tutorial.qdoc @@ -44,13 +44,13 @@ examples/declarative/tutorials/extending directory. Tutorial chapters: \list 1 -\o \l{declarative/tutorials/extending/chapter1-basics}{Creating a New Type} -\o \l{declarative/tutorials/extending/chapter2-methods}{Connecting to C++ Methods and Signals} -\o \l{declarative/tutorials/extending/chapter3-bindings}{Property Binding} -\o \l{declarative/tutorials/extending/chapter4-customPropertyTypes}{Using Custom Property Types} -\o \l{declarative/tutorials/extending/chapter5-listproperties}{Using List Property Types} -\o \l{declarative/tutorials/extending/chapter6-plugins}{Writing an Extension Plugin} -\o \l{qml-extending-tutorial7.html}{In Summary} +\li \l{declarative/tutorials/extending/chapter1-basics}{Creating a New Type} +\li \l{declarative/tutorials/extending/chapter2-methods}{Connecting to C++ Methods and Signals} +\li \l{declarative/tutorials/extending/chapter3-bindings}{Property Binding} +\li \l{declarative/tutorials/extending/chapter4-customPropertyTypes}{Using Custom Property Types} +\li \l{declarative/tutorials/extending/chapter5-listproperties}{Using List Property Types} +\li \l{declarative/tutorials/extending/chapter6-plugins}{Writing an Extension Plugin} +\li \l{qml-extending-tutorial7.html}{In Summary} \endlist */ @@ -92,8 +92,8 @@ properties. Since QML makes extensive use of Qt's \l{Meta-Object System}{meta ob this new class must: \list -\o Inherit from QObject -\o Declare its properties using the Q_PROPERTY macro +\li Inherit from QObject +\li Declare its properties using the Q_PROPERTY macro \endlist Here is our \c PieChart class, defined in \c piechart.h: @@ -290,11 +290,11 @@ We can also use various other property types. QML has built-in support for the t listed in the \l{QML Basic Types} documentation, which includes the following: \list -\o bool, unsigned int, int, float, double, qreal -\o QString, QUrl, QColor -\o QDate, QTime, QDateTime -\o QPoint, QPointF, QSize, QSizeF, QRect, QRectF -\o QVariant +\li bool, unsigned int, int, float, double, qreal +\li QString, QUrl, QColor +\li QDate, QTime, QDateTime +\li QPoint, QPointF, QSize, QSizeF, QRect, QRectF +\li QVariant \endlist If we want to create a property whose type is not supported by QML by default, @@ -409,9 +409,9 @@ loading our own C++ application. To create a plugin library, we need: \list -\o A plugin class that registers our QML types -\o A project file that describes the plugin -\o A \l{Writing a qmldir file}{qmldir} file that tells the QML engine to load the plugin +\li A plugin class that registers our QML types +\li A project file that describes the plugin +\li A \l{Writing a qmldir file}{qmldir} file that tells the QML engine to load the plugin \endlist First, we create a plugin class named \c ChartsPlugin. It subclasses QQmlExtensionPlugin @@ -460,12 +460,12 @@ be used by \c app.qml without import statements. In this tutorial, we've shown the basic steps for creating a QML extension: \list -\o Define new QML types by subclassing QObject and registering them with qmlRegisterType() -\o Add callable methods using Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax -\o Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals -\o Define custom property types if the built-in types are not sufficient -\o Define list property types using QQmlListProperty -\o Create a plugin library by defining a Qt plugin and writing a \c qmldir file +\li Define new QML types by subclassing QObject and registering them with qmlRegisterType() +\li Add callable methods using Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax +\li Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals +\li Define custom property types if the built-in types are not sufficient +\li Define list property types using QQmlListProperty +\li Create a plugin library by defining a Qt plugin and writing a \c qmldir file \endlist diff --git a/doc/src/qml/integrating.qdoc b/doc/src/qml/integrating.qdoc index 2a88246006..83dcaeae74 100644 --- a/doc/src/qml/integrating.qdoc +++ b/doc/src/qml/integrating.qdoc @@ -90,9 +90,9 @@ The following QGraphicsView options are recommended for optimal performance of QML UIs: \list -\o QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState) -\o QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate) -\o QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex) +\li QGraphicsView::setOptimizationFlags(QGraphicsView::DontSavePainterState) +\li QGraphicsView::setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate) +\li QGraphicsScene::setItemIndexMethod(QGraphicsScene::NoIndex) \endlist \section2 Loading QGraphicsWidget Objects in QML diff --git a/doc/src/qml/javascriptblocks.qdoc b/doc/src/qml/javascriptblocks.qdoc index 0c1d4c284c..b9f1e6f0b8 100644 --- a/doc/src/qml/javascriptblocks.qdoc +++ b/doc/src/qml/javascriptblocks.qdoc @@ -200,8 +200,8 @@ in \c script.js: \table \row -\o \snippet doc/src/snippets/qml/integrating-javascript/connectjs.qml 0 -\o \snippet doc/src/snippets/qml/integrating-javascript/script.js 0 +\li \snippet doc/src/snippets/qml/integrating-javascript/connectjs.qml 0 +\li \snippet doc/src/snippets/qml/integrating-javascript/script.js 0 \endtable The \c jsFunction() will now be called whenever MouseArea's \c clicked signal is emitted. @@ -243,10 +243,10 @@ which in turn can call \c factorial() in \c factorial.js, as it has included \table \row -\o {1,2} \snippet doc/src/snippets/qml/integrating-javascript/includejs/app.qml 0 -\o \snippet doc/src/snippets/qml/integrating-javascript/includejs/script.js 0 +\li {1,2} \snippet doc/src/snippets/qml/integrating-javascript/includejs/app.qml 0 +\li \snippet doc/src/snippets/qml/integrating-javascript/includejs/script.js 0 \row -\o \snippet doc/src/snippets/qml/integrating-javascript/includejs/factorial.js 0 +\li \snippet doc/src/snippets/qml/integrating-javascript/includejs/factorial.js 0 \endtable Notice that calling \l {QML:Qt::include()}{Qt.include()} imports all functions from @@ -280,9 +280,9 @@ via a module API; see qmlRegisterModuleApi() for more information. Due to the ability of a JavaScript file to import another script or QML module in this fashion in QtQuick 2.0, some extra semantics are defined: \list -\o a script with imports will not inherit imports from the QML file which imported it (so accessing Component.error will fail, for example) -\o a script without imports will inherit imports from the QML file which imported it (so accessing Component.error will succeed, for example) -\o a shared script (i.e., defined as .pragma library) does not inherit imports from any QML file even if it imports no other scripts +\li a script with imports will not inherit imports from the QML file which imported it (so accessing Component.error will fail, for example) +\li a script without imports will inherit imports from the QML file which imported it (so accessing Component.error will succeed, for example) +\li a shared script (i.e., defined as .pragma library) does not inherit imports from any QML file even if it imports no other scripts \endlist The first semantic is conceptually correct, given that a particular script @@ -339,12 +339,12 @@ parameters. It is occasionally necessary to run some imperative code at application (or component instance) startup. While it is tempting to just include the startup -script as \i {global code} in an external script file, this can have severe limitations +script as \e {global code} in an external script file, this can have severe limitations as the QML environment may not have been fully established. For example, some objects might not have been created or some \l {Property Binding}s may not have been run. \l {QML JavaScript Restrictions} covers the exact limitations of global script code. -The QML \l Component element provides an \i attached \c onCompleted property that +The QML \l Component element provides an \e attached \c onCompleted property that can be used to trigger the execution of script code at startup after the QML environment has been completely established. For example: @@ -371,7 +371,7 @@ component destruction. QML executes standard JavaScript code, with the following restrictions: \list -\o JavaScript code cannot modify the global object. +\li JavaScript code cannot modify the global object. In QML, the global object is constant - existing properties cannot be modified or deleted, and no new properties may be created. @@ -404,7 +404,7 @@ Any attempt to modify the global object - either implicitly or explicitly - will cause an exception. If uncaught, this will result in an warning being printed, that includes the file and line number of the offending code. -\o Global code is run in a reduced scope +\li Global code is run in a reduced scope During startup, if a QML file includes an external JavaScript file with "global" code, it is executed in a scope that contains only the external file itself and @@ -429,7 +429,7 @@ This restriction exists as the QML environment is not yet fully established. To run code after the environment setup has completed, refer to \l {Running JavaScript at Startup}. -\o The value of \c this is currently undefined in QML in the majority of contexts +\li The value of \c this is currently undefined in QML in the majority of contexts The \c this keyword is supported when binding properties from JavaScript. In all other situations, the value of @@ -466,9 +466,9 @@ property may hold a "scarce resource" (image or pixmap). There are several important semantics of scarce resources which should be noted: \list -\o By default, a scarce resource is automatically released by the declarative engine as soon as evaluation of the expression in which the scarce resource is allocated is complete if there are no other references to the resource -\o A client may explicitly preserve a scarce resource, which will ensure that the resource will not be released until all references to the resource are released and the JavaScript engine runs its garbage collector -\o A client may explicitly destroy a scarce resource, which will immediately release the resource +\li By default, a scarce resource is automatically released by the declarative engine as soon as evaluation of the expression in which the scarce resource is allocated is complete if there are no other references to the resource +\li A client may explicitly preserve a scarce resource, which will ensure that the resource will not be released until all references to the resource are released and the JavaScript engine runs its garbage collector +\li A client may explicitly destroy a scarce resource, which will immediately release the resource \endlist In most cases, allowing the engine to automatically release the resource is diff --git a/doc/src/qml/modules.qdoc b/doc/src/qml/modules.qdoc index 27f8ae8fb1..c346f731b1 100644 --- a/doc/src/qml/modules.qdoc +++ b/doc/src/qml/modules.qdoc @@ -43,10 +43,10 @@ explicitly using the \c import statement to import them as modules. For example, an \c import statement is required to use: \list -\o A component defined in another QML file that is not in the same directory -\o A component defined in a QML file located on a remote server -\o A \l{QQmlExtensionPlugin}{QML extension plugin} library (unless the plugin is installed in the same directory) -\o A JavaScript file (note this must be imported using \l {#namespaces}{named imports}) +\li A component defined in another QML file that is not in the same directory +\li A component defined in a QML file located on a remote server +\li A \l{QQmlExtensionPlugin}{QML extension plugin} library (unless the plugin is installed in the same directory) +\li A JavaScript file (note this must be imported using \l {#namespaces}{named imports}) \endlist An \c import statement includes the module name, and possibly a version number. @@ -58,7 +58,7 @@ This imports version 1.0 of the "QtQuick" module into the global namespace. (The library itself must be imported to use any of the \l {QML Elements}, as they are not included in the global namespace by default.) -The \c Qt module is an \i installed module; it is found in the +The \c Qt module is an \e installed module; it is found in the \l{#import-path}{import path}. There are two types of QML modules: located modules (defined by a URL) and installed modules (defined by a URI). @@ -77,11 +77,11 @@ directory using a relative or absolute path, like this: \table \row -\o Directory structure -\o Contents of application.qml +\li Directory structure +\li Contents of application.qml \row -\o +\li \code MyQMLProject |- MyComponents @@ -92,7 +92,7 @@ MyQMLProject |- application.qml \endcode -\o +\li \qml import "../MyComponents" @@ -182,9 +182,9 @@ locations to be searched by the QML engine for a matching module. By default, th contains: \list -\o The directory of the current file -\o The location specified by QLibraryInfo::ImportsPath -\o Paths specified by the \c QML_IMPORT_PATH environment variable +\li The directory of the current file +\li The location specified by QLibraryInfo::ImportsPath +\li Paths specified by the \c QML_IMPORT_PATH environment variable \endlist Additional import paths can be added through QQmlEngine::addImportPath() or the @@ -269,7 +269,7 @@ a module that is imported as a network resource. By default, when a module is imported, its contents are imported into the global namespace. You may choose to import the module into another namespace, either to allow identically-named types to be referenced, or purely for readability. -To import a module into a specific namespace, use the \i as keyword: +To import a module into a specific namespace, use the \e as keyword: \snippet doc/src/snippets/qml/imports/named-imports.qml imports @@ -347,9 +347,9 @@ plugin [] typeinfo \endcode -\bold {# } lines are used for comments. They are ignored by the QML engine. +\b {# } lines are used for comments. They are ignored by the QML engine. -\bold { [] } lines are used to add QML files as types. +\b { [] } lines are used to add QML files as types. is the type being made available, the optional is a version number, and is the (relative) file name of the QML file defining the type. @@ -357,11 +357,11 @@ Installed files do not need to import the module of which they are a part, as th to the other QML files in the module as relative (local) files, but if the module is imported from a remote location, those files must nevertheless be listed in the \c qmldir file. Types which you do not wish to export to users of your module -may be marked with the \c internal keyword: \bold {internal }. +may be marked with the \c internal keyword: \b {internal }. The same type can be provided by different files in different versions, in which case later versions (e.g. 1.2) must precede earlier versions (e.g. 1.0), -since the \i first name-version match is used and a request for a version of a type +since the \e first name-version match is used and a request for a version of a type can be fulfilled by one defined in an earlier version of the module. If a user attempts to import a version earlier than the earliest provided or later than the latest provided, the import produces a runtime error, but if the user imports a version within the range of versions provided, @@ -372,16 +372,16 @@ If multiple are provided, only the first in the search path will be used (regard are provided by directories later in the search path). The versioning system ensures that a given QML file will work regardless of the version -of installed software, since a versioned import \i only imports types for that version, +of installed software, since a versioned import \e only imports types for that version, leaving other identifiers available, even if the actual installed version might otherwise provide those identifiers. -\bold { } lines are used to import javascript files +\b { } lines are used to import javascript files into a Namespace exported by the module. The contents of the script file are made available inside the namespace , which has the version number . -\bold {plugin []} lines are used to add \l{QQmlExtensionPlugin}{QML C++ plugins} to the module. is the name of the library. It is usually not the same as the file name +\b{plugin []} lines are used to add \l{QQmlExtensionPlugin}{QML C++ plugins} to the module. is the name of the library. It is usually not the same as the file name of the plugin binary, which is platform dependent; e.g. the library \c MyAppTypes would produce \c libMyAppTypes.so on Linux and \c MyAppTypes.dll on Windows. @@ -390,7 +390,7 @@ plugin file, or a relative path from the directory containing the \c qmldir file containing the plugin file. By default the engine searches for the plugin library in the directory that contains the \c qmldir file. The plugin search path can be queried with QQmlEngine::pluginPathList() and modified using QQmlEngine::addPluginPath(). When running the \l {QML Viewer}, use the \c -P option to add paths to the plugin search path. -\bold {typeinfo } lines add \l{Writing a qmltypes file}{type description files} to +\b {typeinfo } lines add \l{Writing a qmltypes file}{type description files} to the module that can be read by QML tools such as Qt Creator to get information about the types defined by the module's plugins. is the (relative) file name of a .qmltypes file. @@ -434,9 +434,9 @@ to \c /tmp/imports/My/Module/qmldir to register it. While the qmldump tool covers most cases, it does not work if: \list -\o The plugin uses a \l{QQmlCustomParser}. The component that uses +\li The plugin uses a \l{QQmlCustomParser}. The component that uses the custom parser will not get its members documented. -\o The plugin can not be loaded. In particular if you cross-compiled +\li The plugin can not be loaded. In particular if you cross-compiled the plugin for a different architecture, qmldump will not be able to load it. \endlist diff --git a/doc/src/qml/network.qdoc b/doc/src/qml/network.qdoc index 71f42a4bfe..049bdddf5a 100644 --- a/doc/src/qml/network.qdoc +++ b/doc/src/qml/network.qdoc @@ -41,7 +41,7 @@ Image { } \endqml -Since a \i relative URL is the same +Since a \e relative URL is the same as a relative file, development of QML on regular file systems remains simple: \qml @@ -53,8 +53,8 @@ Image { Network transparency is supported throughout QML, for example: \list -\o Fonts - the \c source property of FontLoader is a URL -\o WebViews - the \c url property of WebView (obviously!) +\li Fonts - the \c source property of FontLoader is a URL +\li WebViews - the \c url property of WebView (obviously!) \endlist Even QML types themselves can be on the network - if the \l {QML Viewer} is used to load @@ -148,10 +148,10 @@ The \c import statement is only network transparent if it has an "as" clause. More specifically: \list -\o \c{import "dir"} only works on local file systems -\o \c{import libraryUri} only works on local file systems -\o \c{import "dir" as D} works network transparently -\o \c{import libraryUrl as U} works network transparently +\li \c{import "dir"} only works on local file systems +\li \c{import libraryUri} only works on local file systems +\li \c{import "dir" as D} works network transparently +\li \c{import libraryUrl as U} works network transparently \endlist \section1 XMLHttpRequest @@ -164,8 +164,8 @@ data from over a network. The XMLHttpRequest API implements the same \l {http://www.w3.org/TR/XMLHttpRequest/}{W3C standard} as many popular web browsers with following exceptions: \list -\i QML's XMLHttpRequest does not enforce the same origin policy. -\i QML's XMLHttpRequest does not support \i synchronous requests. +\li QML's XMLHttpRequest does not enforce the same origin policy. +\li QML's XMLHttpRequest does not support \e synchronous requests. \endlist Additionally, the \c responseXML XML DOM tree currently supported by QML is a reduced subset @@ -174,58 +174,58 @@ browser. The following objects and properties are supported by the QML implemen \table \header -\o \bold {Node} -\o \bold {Document} -\o \bold {Element} -\o \bold {Attr} -\o \bold {CharacterData} -\o \bold {Text} +\li \b {Node} +\li \b {Document} +\li \b {Element} +\li \b {Attr} +\li \b {CharacterData} +\li \b {Text} \row -\o +\li \list -\o nodeName -\o nodeValue -\o nodeType -\o parentNode -\o childNodes -\o firstChild -\o lastChild -\o previousSibling -\o nextSibling -\o attributes +\li nodeName +\li nodeValue +\li nodeType +\li parentNode +\li childNodes +\li firstChild +\li lastChild +\li previousSibling +\li nextSibling +\li attributes \endlist -\o +\li \list -\o xmlVersion -\o xmlEncoding -\o xmlStandalone -\o documentElement +\li xmlVersion +\li xmlEncoding +\li xmlStandalone +\li documentElement \endlist -\o +\li \list -\o tagName +\li tagName \endlist -\o +\li \list -\o name -\o value -\o ownerElement +\li name +\li value +\li ownerElement \endlist -\o +\li \list -\o data -\o length +\li data +\li length \endlist -\o +\li \list -\o isElementContentWhitespace -\o wholeText +\li isElementContentWhitespace +\li wholeText \endlist \endtable diff --git a/doc/src/qml/performance.qdoc b/doc/src/qml/performance.qdoc index 1d6b041803..c5db0e0b2d 100644 --- a/doc/src/qml/performance.qdoc +++ b/doc/src/qml/performance.qdoc @@ -443,8 +443,8 @@ with much worse performance. As such, always try to ensure you meet the followi criteria: \list -\o Avoid using eval() if at all possible -\o Do not delete properties of objects +\li Avoid using eval() if at all possible +\li Do not delete properties of objects \endlist \section1 Common Interface Elements @@ -545,10 +545,10 @@ QML. While the optimal implementation of any such model will depend heavily on use-case it must fulfil, some general guidelines are as follows: \list -\o Be as asynchronous as possible -\o Do all processing in a (low priority) worker thread -\o Batch up backend operations so that (potentially slow) I/O and IPC is minimised -\o Use a sliding slice window to cache results, whose parameters are determined with the help of profiling +\li Be as asynchronous as possible +\li Do all processing in a (low priority) worker thread +\li Batch up backend operations so that (potentially slow) I/O and IPC is minimised +\li Use a sliding slice window to cache results, whose parameters are determined with the help of profiling \endlist It is important to note that using a low-priority worker thread is recommended to @@ -592,15 +592,15 @@ needed (see the upcoming section on lazy initialisation). The following list is a good summary of things to keep in mind when designing a delegate: \list -\o The fewer elements that are in a delegate, the faster they can be created, and thus +\li The fewer elements that are in a delegate, the faster they can be created, and thus the faster the view can be scrolled. -\o Keep the number of bindings in a delegate to a minimum; in particular, use anchors +\li Keep the number of bindings in a delegate to a minimum; in particular, use anchors rather than bindings for relative positioning within a delegate. -\o Set a cacheBuffer to allow asynchronous creation of delegates outside the visible area. +\li Set a cacheBuffer to allow asynchronous creation of delegates outside the visible area. Be mindful that this creates additional delegates and therefore the size of the cacheBuffer must be balanced against additional memory usage. -\o Avoid using ShaderEffect elements within delegates. -\o Never enable clipping on a delegate. +\li Avoid using ShaderEffect elements within delegates. +\li Never enable clipping on a delegate. \endlist \section1 Visual Effects @@ -669,10 +669,10 @@ it is necessary. This may be achieved by using either \l Loader or creating com The Loader is an element which allows dynamic loading and unloading of components. \list -\o Using the "active" property of a Loader, initialisation can be delayed until required. -\o Using the overloaded version of the "setSource()" function, initial property values can +\li Using the "active" property of a Loader, initialisation can be delayed until required. +\li Using the overloaded version of the "setSource()" function, initial property values can be supplied. -\o Setting the Loader \l {Loader::asynchronous}{asynchronous} property to true may also +\li Setting the Loader \l {Loader::asynchronous}{asynchronous} property to true may also improve fluidity while a component is instantiated. \endlist diff --git a/doc/src/qml/propertybinding.qdoc b/doc/src/qml/propertybinding.qdoc index 6dd862f55b..81ca4bbfd3 100644 --- a/doc/src/qml/propertybinding.qdoc +++ b/doc/src/qml/propertybinding.qdoc @@ -33,7 +33,7 @@ \section1 Properties -QML components have \i properties that can be read and modified by other objects. +QML components have \e properties that can be read and modified by other objects. In QML, properties serve many purposes but their main function is to hold to values. Values may be a \l{QML Basic Types}{basic type}, or other QML elements. @@ -157,7 +157,7 @@ JavaScript code. \section1 Types of Properties -Properties may bind to different types, but they are are \i type-safe. That is, +Properties may bind to different types, but they are are \e type-safe. That is, properties only allow you to assign a value that matches the property type. For example, if a property is a real, and if you try to assign a string to it you will get an error. @@ -201,21 +201,21 @@ For more information about the \c children property, please read the \keyword attached-properties \section2 Attached Properties -Certain objects provide additional properties by \i attaching properties to other -objects. For example, the \l Keys element have properties that can \i attach to other QML +Certain objects provide additional properties by \e attaching properties to other +objects. For example, the \l Keys element have properties that can \e attach to other QML objects to provide keyboard handling. \snippet doc/src/snippets/qml/properties.qml list attached property The element \l ListView provides the delegate, \c listdelegate, the property \c isCurrentItem as an attached property. The \c ListView.isCurrentItem -\i{attached property} provides highlight information to the delegate. +\e{attached property} provides highlight information to the delegate. Effectively, the \l ListView element attaches the \c ListView.isCurrentItem property to each delegate it creates. \keyword attached-signalhandlers \section2 Attached Signal Handlers -\i {Attached signal handlers} are similar +\e {Attached signal handlers} are similar to \l{Attached Properties}{attached properties} in that they attach to objects to provide additional functionality to objects. Two prominent elements, \l Component and \l Keys element provide @@ -248,8 +248,8 @@ for more details about list properties and their available operations. \keyword qml-grouped-properties \section2 Grouped Properties -In some cases properties form a logical group and use either the \i dot notation -or \i group notation. +In some cases properties form a logical group and use either the \e dot notation +or \e group notation. Grouped properties may be written both ways: \snippet doc/src/snippets/qml/properties.qml grouped properties @@ -260,8 +260,8 @@ In the element documentation grouped properties are shown using the dot notation Unlike a property definition, which allocates a new, unique storage space for the property, a property alias connects the newly declared property, called the -\i{aliasing property} as a direct reference to an existing property, the -\i{aliased property}. Read or write operations on the aliasing property results +\e{aliasing property} as a direct reference to an existing property, the +\e{aliased property}. Read or write operations on the aliasing property results in a read or write operations on the aliased property, respectively. A property alias declaration is similar to an ordinary property definition: @@ -323,8 +323,8 @@ aliases to reassign children to the \l ListView, creating a tab effect. \section2 Default Properties When imported, QML components will bind declared children to their designated -\i{default properties}. The optional \c default attribute specifies a property -as the \i {default property}. For example, the State element's default property +\e{default properties}. The optional \c default attribute specifies a property +as the \e {default property}. For example, the State element's default property is its \l{State::changes}{changes} property. \l PropertyChanges elements may simply be placed as the \c{State}'s children and they will be bound to the \c changes property. diff --git a/doc/src/qml/qmlcomponents.qdoc b/doc/src/qml/qmlcomponents.qdoc index 21b94f2ae3..6d116df979 100644 --- a/doc/src/qml/qmlcomponents.qdoc +++ b/doc/src/qml/qmlcomponents.qdoc @@ -33,10 +33,10 @@ \title QML Components \brief creating and instantiating components -A \i component is an instantiable QML definition, typically contained in a \c -.qml file. For instance, a Button \i component may be defined in \c Button.qml +A \e component is an instantiable QML definition, typically contained in a \c +.qml file. For instance, a Button \e component may be defined in \c Button.qml file. The \l{The QML Engine}{QML engine} may instantiate this Button -component to create Button \i objects. Alternatively, a component may be defined +component to create Button \e objects. Alternatively, a component may be defined inside a \l Component element. Moreover, the Button definition may also contain other components. A Button @@ -67,12 +67,12 @@ component. Components may incorporate any \l{Qt Quick}{QML feature} such as: \list -\o \l{Property Binding in QML}{Properties} - for binding to data and functions -\o \l{JavaScript Expressions in QML}{JavaScript functions} - for performing routines and logic -\o \l{QML Signal and Handler Event System}{Signals and handlers} - t notify other +\li \l{Property Binding in QML}{Properties} - for binding to data and functions +\li \l{JavaScript Expressions in QML}{JavaScript functions} - for performing routines and logic +\li \l{QML Signal and Handler Event System}{Signals and handlers} - t notify other objects about events -\o \l{QML States}{States} and \l{QML Animation and Transitions}{Transitions} -\o many others +\li \l{QML States}{States} and \l{QML Animation and Transitions}{Transitions} +\li many others \endlist For information about these features, visit the respective overviews or the main Qt Quick \l{Qt Quick}{reference} page. @@ -129,7 +129,7 @@ signal handler executes when the component finishes destruction. \keyword qml-top-level \section1 Top-Level Component -Choosing the \i{top-level} or the \i{root} object of components is an important +Choosing the \e{top-level} or the \e{root} object of components is an important design aspect because the top-level object dictates which properties are accessible outside the component. Some elements are not visual elements and will not have visual properties exposed outside the component. Likewise, some diff --git a/doc/src/qml/qmldate.qdoc b/doc/src/qml/qmldate.qdoc index 7ac200db46..696d97ba1d 100644 --- a/doc/src/qml/qmldate.qdoc +++ b/doc/src/qml/qmldate.qdoc @@ -36,9 +36,9 @@ Functions that accept a locale format may be either an enumeration value: \table - \row \i Locale.LongFormat \i The long version of the string; for example, returning "January" as a month name. - \row \i Locale.ShortFormat \i The short version of the string; for example, returning "Jan" as a month name. - \row \i Locale.NarrowFormat \i A special version for use when space is limited; + \row \li Locale.LongFormat \li The long version of the string; for example, returning "January" as a month name. + \row \li Locale.ShortFormat \li The short version of the string; for example, returning "Jan" as a month name. + \row \li Locale.NarrowFormat \li A special version for use when space is limited; for example, returning "J" as a month name. Note that the narrow format might contain the same text for different months and days or it can even be an empty string if the locale doesn't support narrow names, so you should avoid using it for date formatting. @@ -47,21 +47,21 @@ or a string specifying the format These expressions may be used for format dates: \table - \header \i Expression \i Output - \row \i d \i the day as number without a leading zero (1 to 31) - \row \i dd \i the day as number with a leading zero (01 to 31) - \row \i ddd - \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). - \row \i dddd - \i the long localized day name (e.g. 'Monday' to 'Sunday'). - \row \i M \i the month as number without a leading zero (1 to 12) - \row \i MM \i the month as number with a leading zero (01 to 12) - \row \i MMM - \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). - \row \i MMMM - \i the long localized month name (e.g. 'January' to 'December'). - \row \i yy \i the year as two digit number (00 to 99) - \row \i yyyy \i the year as four digit number. If the year is negative, + \header \li Expression \li Output + \row \li d \li the day as number without a leading zero (1 to 31) + \row \li dd \li the day as number with a leading zero (01 to 31) + \row \li ddd + \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \row \li dddd + \li the long localized day name (e.g. 'Monday' to 'Sunday'). + \row \li M \li the month as number without a leading zero (1 to 12) + \row \li MM \li the month as number with a leading zero (01 to 12) + \row \li MMM + \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li MMMM + \li the long localized month name (e.g. 'January' to 'December'). + \row \li yy \li the year as two digit number (00 to 99) + \row \li yyyy \li the year as four digit number. If the year is negative, a minus sign is prepended in addition. \endtable @@ -74,35 +74,35 @@ 1969): \table - \header \o Format \o Result - \row \o dd.MM.yyyy \o 20.07.1969 - \row \o ddd MMMM d yy \o Sun July 20 69 - \row \o 'The day is' dddd \o The day is Sunday + \header \li Format \li Result + \row \li dd.MM.yyyy \li 20.07.1969 + \row \li ddd MMMM d yy \li Sun July 20 69 + \row \li 'The day is' dddd \li The day is Sunday \endtable These expressions may be used for formatting time: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i H - \i the hour without a leading zero (0 to 23, even with AM/PM display) - \row \i HH - \i the hour with a leading zero (00 to 23, even with AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP or A - \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". - \row \i ap or a - \i use am/pm display. \e ap will be replaced by either "am" or "pm". - \row \i t \i the timezone (for example "CEST") + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li H + \li the hour without a leading zero (0 to 23, even with AM/PM display) + \row \li HH + \li the hour with a leading zero (00 to 23, even with AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP or A + \li use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \li ap or a + \li use am/pm display. \e ap will be replaced by either "am" or "pm". + \row \li t \li the timezone (for example "CEST") \endtable All other input characters will be ignored. Any sequence of characters that @@ -113,10 +113,10 @@ Example format strings (assuming that the QTime is 14:13:09.042) \table - \header \i Format \i Result - \row \i hh:mm:ss.zzz \i 14:13:09.042 - \row \i h:m:s ap \i 2:13:9 pm - \row \i H:m:s a \i 14:13:9 pm + \header \li Format \li Result + \row \li hh:mm:ss.zzz \li 14:13:09.042 + \row \li h:m:s ap \li 2:13:9 pm + \row \li H:m:s a \li 14:13:9 pm \endtable If the date is invalid, an empty string will be returned. diff --git a/doc/src/qml/qmldocument.qdoc b/doc/src/qml/qmldocument.qdoc index 426f135a45..30845999b4 100644 --- a/doc/src/qml/qmldocument.qdoc +++ b/doc/src/qml/qmldocument.qdoc @@ -43,16 +43,16 @@ QML documents are always encoded in UTF-8 format. A QML document always begins with one or more import statements. To prevent elements introduced in later versions from affecting existing QML programs, the element types available within a document are controlled by the imported QML \l {Modules} with -a corresponding \i version. +a corresponding \e version. -QML does \i not have a preprocessor that modifies the document prior to +QML does \e not have a preprocessor that modifies the document prior to presentation to the \l{The QML Engine}{QML engine}, unlike C or C++. The \c import statements do not copy and prepend the code in the document, but instead instruct the QML engine on how to resolve type references found in the document. Any type reference present in a QML document - such as \c Rectangle and \c ListView - including those made within an \l {Inline JavaScript}{JavaScript block} or \l {Property Binding in QML}{property -bindings}, are \i resolved based exclusively on the import statements. At least +bindings}, are \e resolved based exclusively on the import statements. At least one \c import statement must be present such as \c{import QtQuick 2.0}. Each \c id value in a QML document must be unique within that document. They do @@ -65,7 +65,7 @@ A QML document defines a single, top-level \l {QML Components}{QML component}. A QML component is a template that is interpreted by the QML engine to create an object with some predefined behaviour. As it is a template, a single QML component can be "run" multiple times to produce several objects, each of -which are said to be \i instances of the component. +which are said to be \e instances of the component. Once created, instances are not dependent on the component that created them, so they can operate on independent data. Here is an example of a simple "Button" @@ -75,12 +75,12 @@ text property: \table \row -\o Button.qml -\o application.qml +\li Button.qml +\li application.qml \row -\o \snippet doc/src/snippets/qml/qml-documents/qmldocuments.qml document -\o +\li \snippet doc/src/snippets/qml/qml-documents/qmldocuments.qml document +\li \qml import QtQuick 2.0 @@ -99,7 +99,7 @@ Column { \endtable Any snippet of QML code can become a component, just by placing it in the file -".qml" where is the component name, and begins with an \bold +".qml" where is the component name, and begins with an \b uppercase letter. Note that the case of all characters in the are significant on some filesystems, notably UNIX filesystems. It is recommended that the case of the filename matches the case of the component name in QML @@ -113,7 +113,7 @@ load them in other components. \section1 Inline Components In addition to the top-level component that all QML documents define, and any -reusable components placed in separate files, documents may also include \i +reusable components placed in separate files, documents may also include \e inline components. Inline components are declared using the \l Component element, as can be seen in the first example above. Inline components share all the characteristics of regular top-level components and use the same \c import @@ -137,9 +137,9 @@ These final two examples perform identically to the original document. \table \row -\o +\li \snippet doc/src/snippets/qml/qml-documents/inline-component.qml document -\o +\li \snippet doc/src/snippets/qml/qml-documents/inline-text-component.qml document \endtable diff --git a/doc/src/qml/qmlengine.qdoc b/doc/src/qml/qmlengine.qdoc index 0865755c7b..b0754fe3ab 100644 --- a/doc/src/qml/qmlengine.qdoc +++ b/doc/src/qml/qmlengine.qdoc @@ -44,10 +44,10 @@ specified in QML files, plugins, or applications. that provide the essential capabilities for doing this. These are: \list - \o QQmlEngine: A QML engine provides the environment for executing QML code. Every + \li QQmlEngine: A QML engine provides the environment for executing QML code. Every application requires at least one engine instance. - \o QQmlComponent: A component encapsulates QML information. - \o QQmlContext: A context allows an application to expose data to + \li QQmlComponent: A component encapsulates QML information. + \li QQmlContext: A context allows an application to expose data to the QML components created by an engine. \endlist @@ -55,9 +55,9 @@ specified in QML files, plugins, or applications. context, component encapsulation, and visual items. \list - \o QQuickItem - \o QQuickPaintedItem - \o QQuickView + \li QQuickItem + \li QQuickPaintedItem + \li QQuickView \endlist \section2 Declarative Engine @@ -110,11 +110,11 @@ specified in QML files, plugins, or applications. \table \row - \o + \li \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQmlComponent-a \dots 0 \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQmlComponent-b - \o + \li \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQuickView \endtable @@ -195,11 +195,11 @@ specified in QML files, plugins, or applications. \table \row - \o + \li \snippet doc/src/snippets/qml/qtbinding/context-advanced/applicationdata.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/context-advanced/main.cpp 0 - \o + \li \snippet doc/src/snippets/qml/qtbinding/context-advanced/MyItem.qml 0 \endtable @@ -246,8 +246,8 @@ specified in QML files, plugins, or applications. \table \row - \o \snippet doc/src/snippets/qml/qtbinding/functions-qml/MyItem.qml 0 - \o \snippet doc/src/snippets/qml/qtbinding/functions-qml/main.cpp 0 + \li \snippet doc/src/snippets/qml/qtbinding/functions-qml/MyItem.qml 0 + \li \snippet doc/src/snippets/qml/qtbinding/functions-qml/main.cpp 0 \endtable Notice the Q_RETURN_ARG() and Q_ARG() arguments for @@ -261,9 +261,9 @@ specified in QML files, plugins, or applications. \table \row - \o + \li \snippet doc/src/snippets/qml/qtbinding/functions-cpp/MyItem.qml 0 - \o + \li \snippet doc/src/snippets/qml/qtbinding/functions-cpp/myclass.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/functions-cpp/main.cpp 0 @@ -288,9 +288,9 @@ specified in QML files, plugins, or applications. \table \row - \o + \li \snippet doc/src/snippets/qml/qtbinding/signals-qml/MyItem.qml 0 - \o + \li \snippet doc/src/snippets/qml/qtbinding/signals-qml/myclass.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/signals-qml/main.cpp 0 @@ -306,13 +306,13 @@ specified in QML files, plugins, or applications. \table \row - \o + \li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/imageviewer.h start \dots 4 \snippet doc/src/snippets/qml/qtbinding/signals-cpp/imageviewer.h end - \o + \li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/standalone.qml 0 \endtable @@ -331,8 +331,8 @@ specified in QML files, plugins, or applications. \table \row - \o \snippet doc/src/snippets/qml/qtbinding/signals-cpp/main.cpp connections - \o \snippet doc/src/snippets/qml/qtbinding/signals-cpp/MyItem.qml 0 + \li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/main.cpp connections + \li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/MyItem.qml 0 \endtable C++ signals can use enum values as parameters provided that the enum is @@ -381,8 +381,8 @@ specified in QML files, plugins, or applications. \table \row - \o \snippet doc/src/snippets/qml/qtbinding/properties-cpp/applicationdata.h 0 - \o \snippet doc/src/snippets/qml/qtbinding/properties-cpp/MyItem.qml 0 + \li \snippet doc/src/snippets/qml/qtbinding/properties-cpp/applicationdata.h 0 + \li \snippet doc/src/snippets/qml/qtbinding/properties-cpp/MyItem.qml 0 \endtable Notice the \c backgroundColorChanged signal is declared as the NOTIFY signal @@ -438,14 +438,14 @@ specified in QML files, plugins, or applications. return pointers to invalid objects. QML makes the following guarentees: \list - \o An object assigned to a QObject (or QObject-derived) pointer property + \li An object assigned to a QObject (or QObject-derived) pointer property will be valid at the time of assignment. Following assignment, it is the responsibility of the class to subsequently guard this pointer, either through a class specific method or the generic QPointer class. - \o An object assigned to a QVariant will be valid at the time of assignment. + \li An object assigned to a QVariant will be valid at the time of assignment. When assigning an object to a QVariant property, QML will always use a QMetaType::QObjectStar typed QVariant. It is the responsibility of the class @@ -453,7 +453,7 @@ specified in QML files, plugins, or applications. properties is to check the type of the QVariant when it is set and if the type is not handled by your class, reset it to an invalid variant. - \o An object assigned to a QObject (or QObject-derived) list property will + \li An object assigned to a QObject (or QObject-derived) list property will be valid at the time of assignment. Following assignment, it is the responsibility of the class to subsequently diff --git a/doc/src/qml/qmlevents.qdoc b/doc/src/qml/qmlevents.qdoc index 1f2e7a9908..2567dddb2a 100644 --- a/doc/src/qml/qmlevents.qdoc +++ b/doc/src/qml/qmlevents.qdoc @@ -38,8 +38,8 @@ The button may change colors to indicate its state or perform some logic. As well, application needs to know whether the user is clicking the button. The application may need to relay this clicking event to other applications. -QML has a signal and handler mechanism, where the \i signal is the event -and the component responds to the event through the \i handler. The signal +QML has a signal and handler mechanism, where the \e signal is the event +and the component responds to the event through the \e handler. The signal is emitted and the handler is invoked. Placing logic such as scripts or other operations in the handler allows the component to respond to the event. @@ -66,7 +66,7 @@ If the signal has no parameters, the "\c{()}" brackets are optional. If parameters are used, the parameter types must be declared, as for the \c string and \c variant arguments of the \c perform signal. -Adding a signal to an item automatically adds a \i{signal handler} as well. The +Adding a signal to an item automatically adds a \e{signal handler} as well. The signal hander is named \c on, with the first letter of the signal in uppercase. The previous signals have the following signal handlers: \snippet doc/src/snippets/qml/events.qml signal handler declaration diff --git a/doc/src/qml/qmli18n.qdoc b/doc/src/qml/qmli18n.qdoc index 4e546c7ed4..d15beafb38 100644 --- a/doc/src/qml/qmli18n.qdoc +++ b/doc/src/qml/qmli18n.qdoc @@ -47,8 +47,8 @@ QScriptEngine::installTranslatorFunctions(). QML relies on the core internationalization capabilities provided by Qt. These capabilities are described more fully in: \list -\o \l {Internationalization with Qt} -\o \l {Qt Linguist Manual} +\li \l {Internationalization with Qt} +\li \l {Qt Linguist Manual} \endlist You can test a translation with the \l {QML Viewer} using the -translation option. diff --git a/doc/src/qml/qmlintro.qdoc b/doc/src/qml/qmlintro.qdoc index 3290a27bc3..390af69c69 100644 --- a/doc/src/qml/qmlintro.qdoc +++ b/doc/src/qml/qmlintro.qdoc @@ -129,13 +129,13 @@ additional elements are defined inside the light blue rectangle. \e components, often interchangeably. \list -\o When we talk about an \e element, we usually mean the syntactic structure, +\li When we talk about an \e element, we usually mean the syntactic structure, including the name, the opening and closing braces, and its contents. -\o An \e item is an element that has a visual appearance. All items are +\li An \e item is an element that has a visual appearance. All items are elements that inherit \l Item either directly or indirectly. For example, a \l Rectangle is an item, but a \l State is an element because it does not have an intrinsic appearance. -\o A \e component is an element that is defined to be reused. In many cases, +\li A \e component is an element that is defined to be reused. In many cases, components are often items, too. \endlist @@ -333,8 +333,8 @@ the case. Commenting in QML is similar to JavaScript. \list -\o Single line comments start with // and finish at the end of the line. -\o Multi-line comments start with /* and finish with *\/ +\li Single line comments start with // and finish at the end of the line. +\li Multi-line comments start with /* and finish with *\/ \endlist Comments are ignored by the QML engine. They are useful for explaining what @@ -379,15 +379,15 @@ referred to in the JavaScript code, as below: When a property changes value, it can send a signal to notify others of this change. -To receive these signals, simply create a \i{signal handler} named with an +To receive these signals, simply create a \e{signal handler} named with an \e onChanged syntax. For example, the \l TextInput element has a \l{TextInput::}{text} property. When this property changes, the \c textChanged signal is emitted. We can monitor this property for changes with the \c onTextChanged handler. \table -\header \o Property \o Signal \o Signal Handler -\row \o \l{TextInput::}{text} \o \c textChanged \o \c onTextChanged +\header \li Property \li Signal \li Signal Handler +\row \li \l{TextInput::}{text} \li \c textChanged \li \c onTextChanged \endtable The following code shows this in practice: @@ -720,10 +720,10 @@ of their own; they simply arrange their child items in the space allocated to them. Any background color, if desired, must be added to a parent Rectangle. \list -\o \l{#Row}{Row} arranges its children in a row. -\o \l{#Column}{Column} arranges its children in a column. -\o \l{#Grid}{Grid} arranges its children in a grid. -\o \l{#Flow}{Flow} arranges its children like words on a page. +\li \l{#Row}{Row} arranges its children in a row. +\li \l{#Column}{Column} arranges its children in a column. +\li \l{#Grid}{Grid} arranges its children in a grid. +\li \l{#Flow}{Flow} arranges its children like words on a page. \endlist Each of these items provides many of the same properties as the others, diff --git a/doc/src/qml/qmlnumber.qdoc b/doc/src/qml/qmlnumber.qdoc index 099a619c0e..47dc0338c0 100644 --- a/doc/src/qml/qmlnumber.qdoc +++ b/doc/src/qml/qmlnumber.qdoc @@ -44,11 +44,11 @@ Valid formats are: \list - \o 'f' Decimal floating point, e.g. 248.65 - \o 'e' Scientific notation using e character, e.g. 2.4865e+2 - \o 'E' Scientific notation using E character, e.g. 2.4865E+2 - \o 'g' Use the shorter of e or f - \o 'G' Use the shorter of E or f + \li 'f' Decimal floating point, e.g. 248.65 + \li 'e' Scientific notation using e character, e.g. 2.4865e+2 + \li 'E' Scientific notation using E character, e.g. 2.4865E+2 + \li 'g' Use the shorter of e or f + \li 'G' Use the shorter of E or f \endlist If precision is not specified, the precision will be 2. diff --git a/doc/src/qml/qmlplugins.qdoc b/doc/src/qml/qmlplugins.qdoc index e41bba2906..b81c4c5ae1 100644 --- a/doc/src/qml/qmlplugins.qdoc +++ b/doc/src/qml/qmlplugins.qdoc @@ -43,13 +43,13 @@ To write a QML extension plugin: \list 1 - \o Subclass QQmlExtensionPlugin - \o Implement QQmlExtensionPlugin's + \li Subclass QQmlExtensionPlugin + \li Implement QQmlExtensionPlugin's \l{QQmlExtensionPlugin::}{registerTypes()} method - \o Register types with qmlRegisterType() - \o Export the class using the Q_EXPORT_PLUGIN2() macro - \o Write a project file for the plugin - \o Create a \l{Writing a qmldir file}{qmldir file} to describe the plugin + \li Register types with qmlRegisterType() + \li Export the class using the Q_EXPORT_PLUGIN2() macro + \li Write a project file for the plugin + \li Create a \l{Writing a qmldir file}{qmldir file} to describe the plugin \endlist QML extension plugins are for either application-specific or library-like @@ -122,11 +122,11 @@ \section1 Reference \list - \o \l {Tutorial: Writing QML extensions with C++} - contains a chapter + \li \l {Tutorial: Writing QML extensions with C++} - contains a chapter on creating QML plugins. - \o \l{Creating QML Types} - information about registering C++ types into + \li \l{Creating QML Types} - information about registering C++ types into the runtime. - \o \l{How to Create Qt Plugins} - information about Qt plugins + \li \l{How to Create Qt Plugins} - information about Qt plugins \endlist diff --git a/doc/src/qml/qmlruntime.qdoc b/doc/src/qml/qmlruntime.qdoc index a803fabd7a..e5472aed99 100644 --- a/doc/src/qml/qmlruntime.qdoc +++ b/doc/src/qml/qmlruntime.qdoc @@ -50,8 +50,8 @@ the application. This is done by writing a Qt C++ application that loads the QQmlEngine by either: \list -\o Loading the QML file through a QQuickView instance, or -\o Creating a QQmlEngine instance and loading QML files with QQmlComponent +\li Loading the QML file through a QQuickView instance, or +\li Creating a QQmlEngine instance and loading QML files with QQmlComponent \endlist diff --git a/doc/src/qml/qmlsyntax.qdoc b/doc/src/qml/qmlsyntax.qdoc index 1cd6ad7f46..6dfebb5174 100644 --- a/doc/src/qml/qmlsyntax.qdoc +++ b/doc/src/qml/qmlsyntax.qdoc @@ -103,7 +103,7 @@ Rotation { \endcode These expressions can include references to other objects and properties, in which case -a \i binding is established: when the value of the expression changes, the property the +a \e binding is established: when the value of the expression changes, the property the expression has been assigned to is automatically updated to that value. \code @@ -122,15 +122,15 @@ Item { In the example above, the \c text2 object will display the same text as \c text1. If \c text1 is changed, \c text2 is automatically changed to the same value. -Note that to refer to other objects, we use their \i id values. (See below for more -information on the \i id property.) +Note that to refer to other objects, we use their \e id values. (See below for more +information on the \e id property.) \section1 QML Comments Commenting in QML is similar to JavaScript. \list -\o Single line comments start with // and finish at the end of the line. -\o Multiline comments start with /* and finish with *\/ +\li Single line comments start with // and finish at the end of the line. +\li Multiline comments start with /* and finish with *\/ \endlist \snippet doc/src/snippets/qml/comments.qml 0 diff --git a/doc/src/qml/qmltypes.qdoc b/doc/src/qml/qmltypes.qdoc index 9555e54f7e..ae4ad47c3d 100644 --- a/doc/src/qml/qmltypes.qdoc +++ b/doc/src/qml/qmltypes.qdoc @@ -70,14 +70,14 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c Alternatively, these functions provide a way for other types of C++ types to be visible in the QML context. \list - \o \l qmlRegisterUncreatableType() is suited for attached + \li \l qmlRegisterUncreatableType() is suited for attached properties and enum types. - \o \l qmlRegisterTypeNotAvailable() is for + \li \l qmlRegisterTypeNotAvailable() is for reserving a namespace and suited for generating useful errors. - \o \l qmlRegisterInterface() - for registering base or abstract classes for + \li \l qmlRegisterInterface() - for registering base or abstract classes for \l{qml-c++-coercion}{coercion and inheritance}. This is useful for general Qt objects or \l{Qt Objects and Interfaces}{pointers} to objects. - \o \l qmlRegisterExtendedType() - for \l{qml-c++-extension}{extended types} + \li \l qmlRegisterExtendedType() - for \l{qml-c++-extension}{extended types} \endlist \section2 Qt Objects and Interfaces @@ -119,7 +119,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c \l{The Property System}{Property System} and in effect, QML \l{Property Binding in QML}{property bindings} also use Qt properties. - Essentially, a Qt C++ property has a \i write function, \i read function, + Essentially, a Qt C++ property has a \e write function, \e read function, and has a signal function. QML properties are inheritely public, both readable and writable, albeit type-safe. QML properties may also have signals which are emitted when the property value or binding changes. @@ -154,7 +154,7 @@ Q_PROPERTY(int size READ size WRITE setSize NOTIFY shoeChanged) QML}{JavaScript expressions} can perform clean-up operations or call other functions. - \bold{Note:} The QML signal handler will always be named + \b{Note:} The QML signal handler will always be named onChanged, regardless of the name used for the NOTIFY signal in C++. We recommend using Changed() for the NOTIFY signal in C++. @@ -224,9 +224,9 @@ Q_PROPERTY(int size READ size CONSTANT) \section2 Attached Properties Attached properties annotate or add properties to another type or component. - For example, the \l Keys \i{attaching type} contains \i{attached properties} + For example, the \l Keys \e{attaching type} contains \e{attached properties} that other elements may use to respond to key input. Conceptually, attached - properties are a \i type exporting a set of additional properties that can + properties are a \e type exporting a set of additional properties that can be set on any other object instance. The attaching type is a QObject derived type. The properties on the @@ -344,7 +344,7 @@ Q_PROPERTY(int size READ size CONSTANT) \snippet examples/declarative/cppextensions/referenceexamples/properties/example.qml 0 - The \c guests property is a \i{list property} of \c Person objects. A list + The \c guests property is a \e{list property} of \c Person objects. A list of \c Person objects are bound to the \c BirthdayParty's \c host property, and assigns three \c Person objects to the guests property. @@ -370,11 +370,11 @@ Q_PROPERTY(int size READ size CONSTANT) Array types. In particular, QML currently supports: \list - \o \c {QList} - \o \c {QList} - \o \c {QList} - \o \c {QList} and \c{QStringList} - \o \c {QList} + \li \c {QList} + \li \c {QList} + \li \c {QList} + \li \c {QList} and \c{QStringList} + \li \c {QList} \endlist These sequence types are implemented directly in terms of the underlying C++ @@ -398,7 +398,7 @@ Q_PROPERTY(int size READ size CONSTANT) instance of any other sequence type will be passed between QML and C++ as an opaque QVariantList. - \bold {Important Note:} There are some minor differences between the + \b {Important Note:} There are some minor differences between the semantics of such sequence Array types and default JavaScript Array types which result from the use of a C++ storage type in the implementation. In particular, deleting an element from an Array will result in a @@ -412,11 +412,11 @@ Q_PROPERTY(int size READ size CONSTANT) The default-constructed values for each sequence type are as follows: \table - \row \o QList \o integer value 0 - \row \o QList \o real value 0.0 - \row \o QList \o boolean value \c {false} - \row \o QList and QStringList \o empty QString - \row \o QList \o empty QUrl + \row \li QList \li integer value 0 + \row \li QList \li real value 0.0 + \row \li QList \li boolean value \c {false} + \row \li QList and QStringList \li empty QString + \row \li QList \li empty QUrl \endtable If you wish to remove elements from a sequence rather than simply replace @@ -454,7 +454,7 @@ Q_PROPERTY(int size READ size CONSTANT) scenario. Consider a custom type, \c TestElement, that has two properties, \c a and - \c b. Property \c a does \i not have a NOTIFY signal, and property \c b does + \c b. Property \c a does \e not have a NOTIFY signal, and property \c b does have a NOTIFY signal. \code @@ -490,7 +490,7 @@ Q_PROPERTY(int size READ size CONSTANT) A \l{signals and slots}{signal} in Qt C++ is readily available as a \l{QML Signal and Handler Event System}{QML signal}. A signal will have - a corresponding signal \i{handler}, created automatically. The handler + a corresponding signal \e{handler}, created automatically. The handler name will have \c on prepended at the beginning of the name. The first character of the signal is uppercased for the signal handler. The signal parameter is also availabe to the QML signal. @@ -513,9 +513,9 @@ Q_PROPERTY(int size READ size CONSTANT) \l {Connections} element. Additionally, if a property is added to a C++ class, all QML elements - based on that C++ class will have a \i{value-changed} signal handler + based on that C++ class will have a \e{value-changed} signal handler for that property. The name of the signal handler is - \i{onChanged}, with the first letter of the property + \e{onChanged}, with the first letter of the property name being upper case. The \l {Extending QML - Signal Support Example}{Signal Support Example} @@ -699,10 +699,10 @@ Q_PROPERTY(int size READ size CONSTANT) other concerns, extension objects allow limited extension possibilities without direct modifications. - \i{Extension objects} add additional properties to an existing type. + \e{Extension objects} add additional properties to an existing type. Extension objects can only add properties, not signals or methods. An extended type definition allows the programmer to supply an additional type, - known as the \i{extension type}, when registering the class. The + known as the \e{extension type}, when registering the class. The properties are transparently merged with the original target class when used from within QML. diff --git a/doc/src/qml/qmlviewer.qdoc b/doc/src/qml/qmlviewer.qdoc index 9006a053fc..04c6b42966 100644 --- a/doc/src/qml/qmlviewer.qdoc +++ b/doc/src/qml/qmlviewer.qdoc @@ -38,7 +38,7 @@ runtime to load QML documents and also includes additional features useful for the development of QML-based applications. The QML Viewer is a tool for testing and developing QML applications. It is -\i not intended for use in a production environment and should not be used for the +\e not intended for use in a production environment and should not be used for the deployment of QML applications. In those cases, the QML runtime should be invoked from a Qt application instead; see \l {Qt Declarative UI Runtime} for more information. @@ -172,9 +172,9 @@ information about the application's runtime environment through the following pr \table \row -\o \c runtime.isActiveWindow +\li \c runtime.isActiveWindow -\o This property indicates whether the QML Viewer window is the current active +\li This property indicates whether the QML Viewer window is the current active window on the system. It is useful for "pausing" an application, particularly animations, when the QML Viewer loses focus or moves to the background. @@ -193,22 +193,22 @@ Rectangle { } \endqml -\bold{Note:} Since Qt Quick 1.1 this information is accessible outside of the QML Viewer, +\b{Note:} Since Qt Quick 1.1 this information is accessible outside of the QML Viewer, through the \c active property of the \l {QML:Qt::application}{Qt.application} object. \row -\o \c runtime.orientation +\li \c runtime.orientation -\o This property indicates the current orientation of the QML Viewer. +\li This property indicates the current orientation of the QML Viewer. This indicates the orientation currently selected in the QML Viewer's -\i {Settings -> Properties} menu. The \c orientation value can be one of the following: +\e {Settings -> Properties} menu. The \c orientation value can be one of the following: \list -\o \c Orientation.Portrait -\o \c Orientation.Landscape -\o \c Orientation.PortraitInverted (Portrait orientation, upside-down) -\o \c Orientation.LandscapeInverted (Landscape orientation, upside-down) +\li \c Orientation.Portrait +\li \c Orientation.Landscape +\li \c Orientation.PortraitInverted (Portrait orientation, upside-down) +\li \c Orientation.LandscapeInverted (Landscape orientation, upside-down) \endlist When the viewer's orientation changes, the appearance of the loaded QML document diff --git a/doc/src/qml/qtbinding.qdoc b/doc/src/qml/qtbinding.qdoc index 7410836e9c..b480d1292f 100644 --- a/doc/src/qml/qtbinding.qdoc +++ b/doc/src/qml/qtbinding.qdoc @@ -40,11 +40,11 @@ reusable QML components for distribution. You may want to mix QML and C++ for a number of reasons. For example: \list -\o To use functionality defined in a C++ source (for example, when using a C++ Qt-based data model, or +\li To use functionality defined in a C++ source (for example, when using a C++ Qt-based data model, or calling functions in a third-party C++ library) -\o To access functionality in the Qt Declarative module (for example, to dynamically generate +\li To access functionality in the Qt Declarative module (for example, to dynamically generate images using QQmlImageProvider) -\o To write your own QML elements (whether for your applications, or for distribution to others) +\li To write your own QML elements (whether for your applications, or for distribution to others) \endlist To use the Qt Declarative module, you must include and link to the module appropriately, as shown on @@ -59,10 +59,10 @@ embedding QML into C++ applications. There are several core classes in the Qt De that provide the essential capabilities for doing this. These are: \list -\o QQmlEngine: A QML engine provides the environment for executing QML code. Every +\li QQmlEngine: A QML engine provides the environment for executing QML code. Every application requires at least one engine instance. -\o QQmlComponent: A component encapsulates a \l{QML Documents}{QML document}. -\o QQmlContext: A context allows an application to expose data to the QML components +\li QQmlComponent: A component encapsulates a \l{QML Documents}{QML document}. +\li QQmlContext: A context allows an application to expose data to the QML components created by an engine. \endlist @@ -95,10 +95,10 @@ UI code}.) There are a number of ways to extend your QML application through C++. For example, you could: \list -\o Load a QML component and manipulate it (or its children) from C++ -\o Embed a C++ object and its properties directly into a QML component (for example, to make a +\li Load a QML component and manipulate it (or its children) from C++ +\li Embed a C++ object and its properties directly into a QML component (for example, to make a particular C++ object callable from QML, or to replace a dummy list model with a real data set) -\o Define new QML elements (through QObject-based C++ classes) and create them directly from your +\li Define new QML elements (through QObject-based C++ classes) and create them directly from your QML code \endlist @@ -125,11 +125,11 @@ component, which is accessible via QQuickView::rootObject(): \table \row -\o +\li \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQmlComponent-a \dots 0 \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQmlComponent-b -\o +\li \snippet doc/src/snippets/qml/qtbinding/loading/main.cpp QQuickView \endtable @@ -201,11 +201,11 @@ invokes a method on the object instance: \table \row -\o +\li \snippet doc/src/snippets/qml/qtbinding/context-advanced/applicationdata.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/context-advanced/main.cpp 0 -\o +\li \snippet doc/src/snippets/qml/qtbinding/context-advanced/MyItem.qml 0 \endtable @@ -286,8 +286,8 @@ QMetaObject::invokeMethod(). Here is a C++ application that uses this to call a \table \row -\o \snippet doc/src/snippets/qml/qtbinding/functions-qml/MyItem.qml 0 -\o \snippet doc/src/snippets/qml/qtbinding/functions-qml/main.cpp 0 +\li \snippet doc/src/snippets/qml/qtbinding/functions-qml/MyItem.qml 0 +\li \snippet doc/src/snippets/qml/qtbinding/functions-qml/main.cpp 0 \endtable Notice the Q_RETURN_ARG() and Q_ARG() arguments for QMetaObject::invokeMethod() must be specified as @@ -299,9 +299,9 @@ methods on the \c myObject object, which has been set using QQmlContext::setCont \table \row -\o +\li \snippet doc/src/snippets/qml/qtbinding/functions-cpp/MyItem.qml 0 -\o +\li \snippet doc/src/snippets/qml/qtbinding/functions-cpp/myclass.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/functions-cpp/main.cpp 0 @@ -324,9 +324,9 @@ is emitted: \table \row -\o +\li \snippet doc/src/snippets/qml/qtbinding/signals-qml/MyItem.qml 0 -\o +\li \snippet doc/src/snippets/qml/qtbinding/signals-qml/myclass.h 0 \codeline \snippet doc/src/snippets/qml/qtbinding/signals-qml/main.cpp 0 @@ -340,13 +340,13 @@ C++ object are connected to through \c onImagedChanged and \c onLoadingError sig \table \row -\o +\li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/imageviewer.h start \dots 4 \snippet doc/src/snippets/qml/qtbinding/signals-cpp/imageviewer.h end -\o +\li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/standalone.qml 0 \endtable @@ -362,8 +362,8 @@ instead to create the signal handler: \table \row -\o \snippet doc/src/snippets/qml/qtbinding/signals-cpp/main.cpp connections -\o \snippet doc/src/snippets/qml/qtbinding/signals-cpp/MyItem.qml 0 +\li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/main.cpp connections +\li \snippet doc/src/snippets/qml/qtbinding/signals-cpp/MyItem.qml 0 \endtable C++ signals can use enum values as parameters provided that the enum is declared in the @@ -410,8 +410,8 @@ property. This property can be written to and read from QML: \table \row -\o \snippet doc/src/snippets/qml/qtbinding/properties-cpp/applicationdata.h 0 -\o \snippet doc/src/snippets/qml/qtbinding/properties-cpp/MyItem.qml 0 +\li \snippet doc/src/snippets/qml/qtbinding/properties-cpp/applicationdata.h 0 +\li \snippet doc/src/snippets/qml/qtbinding/properties-cpp/MyItem.qml 0 \endtable Notice the \c backgroundColorChanged signal is declared as the NOTIFY signal for the @@ -432,20 +432,20 @@ functions - must be of a type that is recognizable by QML. By default, QML recognizes the following data types: \list -\o bool -\o unsigned int, int -\o float, double, qreal -\o QString -\o QUrl -\o QColor -\o QDate, QTime, QDateTime -\o QPoint, QPointF -\o QSize, QSizeF -\o QRect, QRectF -\o QVariant -\o QVariantList, QVariantMap -\o QObject* -\o Enumerations declared with Q_ENUMS() +\li bool +\li unsigned int, int +\li float, double, qreal +\li QString +\li QUrl +\li QColor +\li QDate, QTime, QDateTime +\li QPoint, QPointF +\li QSize, QSizeF +\li QRect, QRectF +\li QVariant +\li QVariantList, QVariantMap +\li QObject* +\li Enumerations declared with Q_ENUMS() \endlist To allow a custom C++ type to be created or used in QML, the C++ class must be registered as a QML @@ -464,12 +464,12 @@ converted to JavaScript array and object values, repectively: \table \header -\o Type -\o String format -\o Example +\li Type +\li String format +\li Example \row -\o \snippet doc/src/snippets/qml/qtbinding/variantlistmap/MyItem.qml 0 -\o \snippet doc/src/snippets/qml/qtbinding/variantlistmap/main.cpp 0 +\li \snippet doc/src/snippets/qml/qtbinding/variantlistmap/MyItem.qml 0 +\li \snippet doc/src/snippets/qml/qtbinding/variantlistmap/main.cpp 0 \endtable This produces output like: @@ -535,45 +535,45 @@ pass simple values from QML to C++. \table \header -\o Type -\o String format -\o Example +\li Type +\li String format +\li Example \row -\o QColor -\o Color name, "#RRGGBB", "#RRGGBBAA" -\o "red", "#ff0000", "#ff000000" +\li QColor +\li Color name, "#RRGGBB", "#RRGGBBAA" +\li "red", "#ff0000", "#ff000000" \row -\o QDate -\o "YYYY-MM-DD" -\o "2010-05-31" +\li QDate +\li "YYYY-MM-DD" +\li "2010-05-31" \row -\o QPoint -\o "x,y" -\o "10,20" +\li QPoint +\li "x,y" +\li "10,20" \row -\o QRect -\o "x,y,WidthxHeight" -\o "50,50,100x100" +\li QRect +\li "x,y,WidthxHeight" +\li "50,50,100x100" \row -\o QSize -\o "WidthxHeight" -\o "100x200" +\li QSize +\li "WidthxHeight" +\li "100x200" \row -\o QTime -\o "hh:mm:ss" -\o "14:22:55" +\li QTime +\li "hh:mm:ss" +\li "14:22:55" \row -\o QUrl -\o URL string -\o "http://www.example.com" +\li QUrl +\li URL string +\li "http://www.example.com" \row -\o QVector3D -\o "x,y,z" -\o "0,1,0" +\li QVector3D +\li "x,y,z" +\li "0,1,0" \row -\o Enumeration value -\o Enum value name -\o "AlignRight" +\li Enumeration value +\li Enum value name +\li "AlignRight" \endtable (More details on these string formats and types can be found in the @@ -615,16 +615,16 @@ in order to update the resources in the package. To use the resource system in a mixed QML/C++ application: \list -\o Create a \c .qrc \l {The Qt Resource System}{resource collection file} that lists resource +\li Create a \c .qrc \l {The Qt Resource System}{resource collection file} that lists resource files in XML format -\o From C++, load the main QML file as a resource using the \c :/ prefix or as a URL with the +\li From C++, load the main QML file as a resource using the \c :/ prefix or as a URL with the \c qrc scheme \endlist Once this is done, all files specified by relative paths in QML will be loaded from the resource system instead. Use of the resource system is completely transparent to the QML layer; this means all QML code should refer to resource files using relative -paths and should \i not use the \c qrc scheme. This scheme should only be used from +paths and should \e not use the \c qrc scheme. This scheme should only be used from C++ code for referring to resource files. Here is a application packaged using the \l {The Qt Resource System}{Qt resource system}. diff --git a/doc/src/qml/qtdeclarative.qdoc b/doc/src/qml/qtdeclarative.qdoc index 9d14f7fc57..20d1c40d66 100644 --- a/doc/src/qml/qtdeclarative.qdoc +++ b/doc/src/qml/qtdeclarative.qdoc @@ -95,7 +95,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName); \endcode - The former is the standard form which registers the type \i T as a new type. + The former is the standard form which registers the type \e T as a new type. The latter allows a particular revision of a class to be registered in a specified version (see \l {QML Type Versioning}). @@ -245,7 +245,7 @@ may be registered into any given namespace (combination of \a uri, \a versionMajor and \a versionMinor). This function should be used to register a module API provider function which returns a QJSValue as a module API. - \bold{NOTE:} QJSValue module API properties will \bold{not} trigger binding re-evaluation if changed. + \b{NOTE:} QJSValue module API properties will \b{not} trigger binding re-evaluation if changed. Usage: \code diff --git a/doc/src/qml/qtjavascript.qdoc b/doc/src/qml/qtjavascript.qdoc index 394435f77b..0775730dd3 100644 --- a/doc/src/qml/qtjavascript.qdoc +++ b/doc/src/qml/qtjavascript.qdoc @@ -64,7 +64,7 @@ Custom properties can be made available to scripts by registering them with the script engine. This is most easily done by setting - properties of the script engine's \i{Global Object}: + properties of the script engine's \e{Global Object}: \snippet doc/src/snippets/qtjavascript/registeringvalues/main.cpp 0 diff --git a/doc/src/qml/qtprogrammers.qdoc b/doc/src/qml/qtprogrammers.qdoc index 9338a2c29f..fd47d9bf58 100644 --- a/doc/src/qml/qtprogrammers.qdoc +++ b/doc/src/qml/qtprogrammers.qdoc @@ -31,7 +31,7 @@ \title QML for Qt Programmers \brief learning QML for programmers with Qt knowledge -While QML does not require Qt knowledge to use, if you \i are already familiar with Qt, +While QML does not require Qt knowledge to use, if you \e are already familiar with Qt, much of your knowledge is directly relevant to learning and using QML. Of course, an application with a user interface defined in QML also uses Qt for all the non-UI logic. @@ -41,14 +41,14 @@ logic. QML provides direct access to the following concepts from Qt: \list - \o QAction - the \l {QML Basic Types}{action} type - \o QObject signals and slots - available as functions to call in JavaScript - \o QObject properties - available as variables in JavaScript - \o QWidget - QQuickView is a QML-displaying widget - \o Qt models - used directly in data binding (QAbstractItemModel) + \li QAction - the \l {QML Basic Types}{action} type + \li QObject signals and slots - available as functions to call in JavaScript + \li QObject properties - available as variables in JavaScript + \li QWidget - QQuickView is a QML-displaying widget + \li Qt models - used directly in data binding (QAbstractItemModel) \endlist -Qt knowledge is \i required for \l{Extending QML with C++}, +Qt knowledge is \e required for \l{Extending QML with C++}, and also for \l{Integrating QML Code with existing Qt UI code}. \section1 QML Items Compared with Widgets @@ -60,10 +60,10 @@ look and feel of view delegates, QML Items can be used for this as well. There are three structurally different types of widget: \list - \o Simple widgets that are not used as parents (QLabel, QCheckBox, QToolButton, etc.) - \o Parent widgets that are normally used as parents to other widgets (QGroupBox, + \li Simple widgets that are not used as parents (QLabel, QCheckBox, QToolButton, etc.) + \li Parent widgets that are normally used as parents to other widgets (QGroupBox, QStackedWidget, QTabWidget, etc.) - \o Compound widgets that are internally composed of child widgets (QComboBox, + \li Compound widgets that are internally composed of child widgets (QComboBox, QSpinBox, QFileDialog, QTabWidget, etc.) \endlist @@ -128,9 +128,9 @@ requirement that they be wholly contained ("clipped") to the parent (although th This difference has rather far-reaching consequences, for example: \list -\o A shadow or highlight around a widget could be a child of that widget. -\o Particle effects can flow outside the object where they originate. -\o Transitioning animations can "hide" items by visibly moving them beyond +\li A shadow or highlight around a widget could be a child of that widget. +\li Particle effects can flow outside the object where they originate. +\li Transitioning animations can "hide" items by visibly moving them beyond the screen bounds. \endlist diff --git a/doc/src/qml/scope.qdoc b/doc/src/qml/scope.qdoc index 649653f9e3..15cebc735d 100644 --- a/doc/src/qml/scope.qdoc +++ b/doc/src/qml/scope.qdoc @@ -128,7 +128,7 @@ require the use of the JavaScript \c this property. Care must be used when accessing \l {Attached Properties} from bindings due to their interaction with the scope object. Conceptually attached properties -exist on \i all objects, even if they only have an effect on a subset of those. +exist on \e all objects, even if they only have an effect on a subset of those. Consequently unqualified attached property reads will always resolve to an attached property on the scope object, which is not always what the programmer intended. diff --git a/doc/src/qml/security.qdoc b/doc/src/qml/security.qdoc index 262e560d33..190d6930c5 100644 --- a/doc/src/qml/security.qdoc +++ b/doc/src/qml/security.qdoc @@ -61,21 +61,21 @@ perform appropriate checks on untrusted data it loads. A non-exhaustive list of the ways you could shoot yourself in the foot is: \list - \i Using \c import to import QML or JavaScript you do not control. BAD - \i Using \l Loader to import QML you do not control. BAD - \i Using \l{XMLHttpRequest}{XMLHttpRequest} to load data you do not control and executing it. BAD + \li Using \c import to import QML or JavaScript you do not control. BAD + \li Using \l Loader to import QML you do not control. BAD + \li Using \l{XMLHttpRequest}{XMLHttpRequest} to load data you do not control and executing it. BAD \endlist However, the above does not mean that you have no use for the network transparency of QML. -There are many good and useful things you \i can do: +There are many good and useful things you \e can do: \list - \i Create \l Image elements with source URLs of any online images. GOOD - \i Use XmlListModel to present online content. GOOD - \i Use \l{XMLHttpRequest}{XMLHttpRequest} to interact with online services. GOOD + \li Create \l Image elements with source URLs of any online images. GOOD + \li Use XmlListModel to present online content. GOOD + \li Use \l{XMLHttpRequest}{XMLHttpRequest} to interact with online services. GOOD \endlist -The only reason this page is necessary at all is that JavaScript, when run in a \i{web browser}, +The only reason this page is necessary at all is that JavaScript, when run in a \e{web browser}, has quite many restrictions. With QML, you should neither rely on similar restrictions, nor worry about working around them. */ diff --git a/doc/src/qtdeclarative.qdoc b/doc/src/qtdeclarative.qdoc index 9669b6517a..d9b9234c90 100644 --- a/doc/src/qtdeclarative.qdoc +++ b/doc/src/qtdeclarative.qdoc @@ -55,14 +55,14 @@ winning App across mobile, embedded, and desktop platforms. QML Essentials \enddiv \list - \o \l{QML Components}{Components} - \o \l{Properties and Property Binding in QML}{Properties and Property Binding} - \o \l{JavaScript Expressions in QML}{JavaScript Code} - \o \l{QML Signal and Handler Event System}{Signal and Handler Event System} - \o \l{QML Modules}{Modules} + \li \l{QML Components}{Components} + \li \l{Properties and Property Binding in QML}{Properties and Property Binding} + \li \l{JavaScript Expressions in QML}{JavaScript Code} + \li \l{QML Signal and Handler Event System}{Signal and Handler Event System} + \li \l{QML Modules}{Modules} \endlist \list - \o \l{What's New in Qt Quick 2}{What's New in Qt Quick} + \li \l{What's New in Qt Quick 2}{What's New in Qt Quick} \endlist \enddiv \div {class="threecolumn_piece"} @@ -70,10 +70,10 @@ winning App across mobile, embedded, and desktop platforms. QML Engine \enddiv \list - \o \l{The QML Engine} - \o \l{QML Global Object} - \o \l{Dynamic Object Management in QML}{Dynamic Object Management} - \o \l{QML Performance}{Performance} + \li \l{The QML Engine} + \li \l{QML Global Object} + \li \l{Dynamic Object Management in QML}{Dynamic Object Management} + \li \l{QML Performance}{Performance} \endlist \enddiv \div {class=" threecolumn_piece"} @@ -81,12 +81,12 @@ winning App across mobile, embedded, and desktop platforms. Reference \enddiv \list - \o \l{QML Syntax} - \o \l{QML Basic Types}{Data Types} - \o \l{QML Coding Conventions}{Coding Conventions} - \o \l{QML Security}{Security Model} - \o \l{QML Scope}{Scope Model} - \o \l{QML Documents}{Documents} + \li \l{QML Syntax} + \li \l{QML Basic Types}{Data Types} + \li \l{QML Coding Conventions}{Coding Conventions} + \li \l{QML Security}{Security Model} + \li \l{QML Scope}{Scope Model} + \li \l{QML Documents}{Documents} \endlist \enddiv \div {class="threecolumn_piece"} @@ -94,10 +94,10 @@ winning App across mobile, embedded, and desktop platforms. QML Bindings with Qt C++ \enddiv \list - \o \l{Creating QML Types} - \o \l{QML Plugins} - \o \l{Exposing C++ Models} - \o \l{Integrating QML Code with Existing Qt UI Code}{Qt Gui Porting Information} + \li \l{Creating QML Types} + \li \l{QML Plugins} + \li \l{Exposing C++ Models} + \li \l{Integrating QML Code with Existing Qt UI Code}{Qt Gui Porting Information} \endlist \enddiv \div {class=" threecolumn_piece"} @@ -105,9 +105,9 @@ winning App across mobile, embedded, and desktop platforms. Tools \enddiv \list - \o \l{QML Internationalization}{Internationalization} - \o \l{QtQuickTest Reference Documentation} - \o \l{Debugging QML} + \li \l{QML Internationalization}{Internationalization} + \li \l{QtQuickTest Reference Documentation} + \li \l{Debugging QML} \endlist \enddiv \enddiv @@ -122,10 +122,10 @@ winning App across mobile, embedded, and desktop platforms. Graphics and Special Effects \enddiv \list - \o \l{Qt Quick Basic Elements}{Basic Elements} - \o \l{Painting with Canvas API} - \o \l{Using the Qt Quick Particle System}{Particle Effects} - \o \l{Shader Effects in QML}{Shader Effects} + \li \l{Qt Quick Basic Elements}{Basic Elements} + \li \l{Painting with Canvas API} + \li \l{Using the Qt Quick Particle System}{Particle Effects} + \li \l{Shader Effects in QML}{Shader Effects} \endlist \enddiv \div {class="threecolumn_piece"} @@ -133,9 +133,9 @@ winning App across mobile, embedded, and desktop platforms. Anchoring and Layouts \enddiv \list - \o \l{Component Layouts} - \o \l{Layouts with Anchors} - \o \l{QML Right-to-left User Interfaces}{Right-to-left User Interfaces} + \li \l{Component Layouts} + \li \l{Layouts with Anchors} + \li \l{QML Right-to-left User Interfaces}{Right-to-left User Interfaces} \endlist \enddiv \div {class="threecolumn_piece"} @@ -143,9 +143,9 @@ winning App across mobile, embedded, and desktop platforms. Mouse and Keyboard Input \enddiv \list - \o \l{QML Mouse Events}{Mouse Events} - \o \l{QML Text Handling and Validators}{Text Handling and Validators} - \o \l{Keyboard Focus in QML}{Keyboard Focus} + \li \l{QML Mouse Events}{Mouse Events} + \li \l{QML Text Handling and Validators}{Text Handling and Validators} + \li \l{Keyboard Focus in QML}{Keyboard Focus} \endlist \enddiv \div {class="threecolumn_piece"} @@ -153,8 +153,8 @@ winning App across mobile, embedded, and desktop platforms. States and Transitions \enddiv \list - \o \l{QML States}{States} - \o \l{QML Animation and Transitions}{Animation and Transitions} + \li \l{QML States}{States} + \li \l{QML Animation and Transitions}{Animation and Transitions} \endlist \enddiv \div {class="threecolumn_piece"} @@ -162,7 +162,7 @@ winning App across mobile, embedded, and desktop platforms. Data with Models and Views \enddiv \list - \o \l{QML Models and Views}{Models and Views} + \li \l{QML Models and Views}{Models and Views} \endlist \enddiv \div {class="threecolumn_piece"} @@ -170,8 +170,8 @@ winning App across mobile, embedded, and desktop platforms. Data Storage and Resources \enddiv \list - \o \l{QML Local Storage}{SQL Local Storage} - \o \l{Resource Loading and Network Transparency in QML}{Resources and Network Transparency} + \li \l{QML Local Storage}{SQL Local Storage} + \li \l{Resource Loading and Network Transparency in QML}{Resources and Network Transparency} \endlist \enddiv \enddiv diff --git a/doc/src/qtquick2/anchor-layout.qdoc b/doc/src/qtquick2/anchor-layout.qdoc index 6e56768f8a..fb2d8b7d83 100644 --- a/doc/src/qtquick2/anchor-layout.qdoc +++ b/doc/src/qtquick2/anchor-layout.qdoc @@ -33,7 +33,7 @@ \target anchor-layout In addition to the more traditional \l Grid, \l Row, and \l Column, -QML also provides a way to layout items using the concept of \i anchors. +QML also provides a way to layout items using the concept of \e anchors. Each item can be thought of as having a set of 7 invisible "anchor lines": \l {Item::anchors.left}{left}, \l {Item::anchors.horizontalCenter}{horizontalCenter}, \l {Item::anchors.right}{right}, \l {Item::anchors.top}{top}, @@ -43,7 +43,7 @@ and \l {Item::anchors.bottom}{bottom}. \image edges_qml.png The baseline (not pictured above) corresponds to the imaginary line on which -text would sit. For items with no text it is the same as \i top. +text would sit. For items with no text it is the same as \e top. The QML anchoring system allows you to define relationships between the anchor lines of different items. For example, you can write: @@ -52,7 +52,7 @@ Rectangle { id: rect1; ... } Rectangle { id: rect2; anchors.left: rect1.right; ... } \endcode -In this case, the left edge of \i rect2 is bound to the right edge of \i 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 @@ -67,8 +67,8 @@ Rectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... \image edge3.png By specifying multiple horizontal or vertical anchors you can control the size of an item. Below, -\i rect2 is anchored to the right of \i rect1 and the left of \i rect3. If either of the blue -rectangles are moved, \i rect2 will stretch and shrink as necessary: +\e rect2 is anchored to the right of \e rect1 and the left of \e rect3. If either of the blue +rectangles are moved, \e rect2 will stretch and shrink as necessary: \code Rectangle { id: rect1; x: 0; ... } @@ -84,7 +84,7 @@ and horizontalCenter anchors to the verticalCenter and horizontalCenter of the t \section1 Anchor Margins and Offsets -The anchoring system also allows \i margins and \i offsets to be specified for an item's anchors. +The anchoring system also allows \e margins and \e offsets to be specified for an item's anchors. Margins specify the amount of empty space to leave to the outside of an item's anchor, while offsets allow positioning to be manipulated using the center anchor lines. An item can specify its anchor margins individually through \l {Item::anchors.leftMargin}{leftMargin}, @@ -104,11 +104,11 @@ 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 \i 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 -\note Anchor margins only apply to anchors; they are \i not a generic means of applying margins to an \l Item. +\note Anchor margins only apply to anchors; they are \e not a generic means of applying margins to an \l Item. If an anchor margin is specified for an edge but the item is not anchored to any item on that edge, the margin is not applied. diff --git a/doc/src/qtquick2/animation.qdoc b/doc/src/qtquick2/animation.qdoc index cf656fb209..7e74f06abf 100644 --- a/doc/src/qtquick2/animation.qdoc +++ b/doc/src/qtquick2/animation.qdoc @@ -34,27 +34,27 @@ \keyword qml-animation-elements \section1 Animation and Transitions Elements \list -\o \l {Transition} - Animates transitions during state changes -\o \l {SequentialAnimation} - Runs animations sequentially -\o \l {ParallelAnimation} - Runs animations in parallel -\o \l {Behavior} - Specifies a default animation for property changes -\o \l {PropertyAction} - Sets immediate property changes during animation -\o \l {PauseAnimation} - Introduces a pause in an animation -\o \l {SmoothedAnimation} - Allows a property to smoothly track a value -\o \l {SpringAnimation} - Allows a property to track a value in a spring-like motion -\o \l {ScriptAction} - Runs scripts during an animation +\li \l {Transition} - Animates transitions during state changes +\li \l {SequentialAnimation} - Runs animations sequentially +\li \l {ParallelAnimation} - Runs animations in parallel +\li \l {Behavior} - Specifies a default animation for property changes +\li \l {PropertyAction} - Sets immediate property changes during animation +\li \l {PauseAnimation} - Introduces a pause in an animation +\li \l {SmoothedAnimation} - Allows a property to smoothly track a value +\li \l {SpringAnimation} - Allows a property to track a value in a spring-like motion +\li \l {ScriptAction} - Runs scripts during an animation \endlist \keyword qml-property-animation-elements Elements that animate properties based on data types \list -\o \l {PropertyAnimation} - Animates property changes -\o \l {NumberAnimation} - Animates properties of type qreal -\o \l {Vector3dAnimation} - Animates properties of type QVector3d -\o \l {ColorAnimation} - Animates color changes -\o \l {RotationAnimation} - Animates rotations -\o \l {ParentAnimation} - Animates parent changes -\o \l {AnchorAnimation} - Animates anchor changes +\li \l {PropertyAnimation} - Animates property changes +\li \l {NumberAnimation} - Animates properties of type qreal +\li \l {Vector3dAnimation} - Animates properties of type QVector3d +\li \l {ColorAnimation} - Animates color changes +\li \l {RotationAnimation} - Animates rotations +\li \l {ParentAnimation} - Animates parent changes +\li \l {AnchorAnimation} - Animates anchor changes \endlist In QML, animations are created by applying animation elements to property @@ -78,7 +78,7 @@ directly. This may be done in signal handlers or attached properties. \snippet doc/src/snippets/qml/animation.qml direct property change -However, to create more control, \i {property animations} apply smooth movements +However, to create more control, \e {property animations} apply smooth movements by interpolating values between property value changes. Property animations provide timing controls and allows different interpolations through \l{qml-easing-animation}{easing curves}. @@ -123,7 +123,7 @@ that the transition applies to any state change. \section2 Default Animation as Behaviors -Default property animations are set using \i {behavior animations}. Animations +Default property animations are set using \e {behavior animations}. Animations declared in \l {Behavior} elements apply to the property and animates any property value changes. However, Behavior elements have an \c enabled property to purposely enable or disable the behavior animations. @@ -144,7 +144,7 @@ demonstration of behavioral animations. \section1 Playing Animations in Parallel or in Sequence -Animations can run \i {in parallel} or \i {in sequence}. Parallel animations +Animations can run \e {in parallel} or \e {in sequence}. Parallel animations will play a group of animations at the same time while sequential animations play a group of animations in order: one after the other. Grouping animations in \l{SequentialAnimation} and \l{ParallelAnimation} will play the animations in @@ -202,22 +202,22 @@ of the different easing types. In addition, QML provides several other elements useful for animation: \list -\o PauseAnimation: enables pauses during animations -\o ScriptAction: allows JavaScript to be executed during an animation, and can +\li PauseAnimation: enables pauses during animations +\li ScriptAction: allows JavaScript to be executed during an animation, and can be used together with StateChangeScript to reused existing scripts -\o PropertyAction: changes a property \i immediately during an animation, +\li PropertyAction: changes a property \e immediately during an animation, without animating the property change \endlist These are specialized animation elements that animate different property types \list -\o SmoothedAnimation: a specialized NumberAnimation that provides smooth +\li SmoothedAnimation: a specialized NumberAnimation that provides smooth changes in animation when the target value changes -\o SpringAnimation: provides a spring-like animation with specialized +\li SpringAnimation: provides a spring-like animation with specialized attributes such as \l {SpringAnimation::}{mass}, \l{SpringAnimation::}{damping} and \l{SpringAnimation::}{epsilon} -\o ParentAnimation: used for animating a parent change (see ParentChange) -\o AnchorAnimation: used for animating an anchor change (see AnchorChanges) +\li ParentAnimation: used for animating a parent change (see ParentChange) +\li AnchorAnimation: used for animating an anchor change (see AnchorChanges) \endlist \section1 Sharing Animation Instances diff --git a/doc/src/qtquick2/basicelements.qdoc b/doc/src/qtquick2/basicelements.qdoc index ae212f1964..99eb83bca2 100644 --- a/doc/src/qtquick2/basicelements.qdoc +++ b/doc/src/qtquick2/basicelements.qdoc @@ -31,7 +31,7 @@ \title Qt Quick Basic Elements \brief introduction to the Qt Quick Elements -Qt Quick includes \i elements for placing components. These can be combined +Qt Quick includes \e elements for placing components. These can be combined to form other components. \code @@ -40,15 +40,15 @@ import QtQuick 2.0 \section1 Basic Elements This is a list of some of the elements readily available for users. \list -\o \l {Item} -\o \l {Rectangle} -\o \l {Image} -\o \l {Text} -\o \l {TextInput} -\o \l {TextEdit} -\o \l {FocusScope} -\o \l {Component} -\o \l {MouseArea} +\li \l {Item} +\li \l {Rectangle} +\li \l {Image} +\li \l {Text} +\li \l {TextInput} +\li \l {TextEdit} +\li \l {FocusScope} +\li \l {Component} +\li \l {MouseArea} \endlist For a complete list of QML elements, please visit the \l {QML Elements} page. diff --git a/doc/src/qtquick2/behaviors-and-states.qdoc b/doc/src/qtquick2/behaviors-and-states.qdoc index 626b6e61e3..16ee0f9ba5 100644 --- a/doc/src/qtquick2/behaviors-and-states.qdoc +++ b/doc/src/qtquick2/behaviors-and-states.qdoc @@ -78,8 +78,8 @@ problem occurs because we have used a Behavior to animate the change in color, a To state the problem more formally, using States and Behaviors together can cause unexpected behavior when: \list -\o a Behavior is used to animate a property change, specifically when moving from an explicitly defined state back to the implicit base state; and -\o this Behavior can be interrupted to (re-)enter an explicitly defined state. +\li a Behavior is used to animate a property change, specifically when moving from an explicitly defined state back to the implicit base state; and +\li this Behavior can be interrupted to (re-)enter an explicitly defined state. \endlist The problem occurs because of the way the base state is defined for QML: as the "snapshot" state of the application just prior to entering an explicitly defined state. In this case, if we are in the process of animating from green back diff --git a/doc/src/qtquick2/canvaspainting.qdoc b/doc/src/qtquick2/canvaspainting.qdoc index 8590c74913..3b1f742b8f 100644 --- a/doc/src/qtquick2/canvaspainting.qdoc +++ b/doc/src/qtquick2/canvaspainting.qdoc @@ -34,8 +34,8 @@ \section1 Canvas Element \list - \o \l{Canvas} - \o \l{Context2D} + \li \l{Canvas} + \li \l{Context2D} \endlist The Canvas and Context2D elements implement the \l{HTML Canvas API 2D Context} diff --git a/doc/src/qtquick2/elements.qdoc b/doc/src/qtquick2/elements.qdoc index 4dde7216e5..90d38d7ecb 100644 --- a/doc/src/qtquick2/elements.qdoc +++ b/doc/src/qtquick2/elements.qdoc @@ -45,154 +45,154 @@ To see the QML elements listed by functional area, see the \section1 Basic QML Elements \list -\o \l {Item} - Basic item element inherited by QML elements -\o \l {Component} - Encapsulates QML elements during importing -\o \l {QtObject} {QtObject} - Basic element containing only the \c {objectName} property +\li \l {Item} - Basic item element inherited by QML elements +\li \l {Component} - Encapsulates QML elements during importing +\li \l {QtObject} {QtObject} - Basic element containing only the \c {objectName} property \endlist \section1 Graphics \list -\o \l {Rectangle} - A rectangle element -\o \l {Image} - For incorporating bitmaps into a scene -\o \l {BorderImage} - Allows the use of images as borders -\o \l {AnimatedImage} - For playing animations stored in a series of frames -\o \l {Gradient} - For defining a color gradient -\o \l {GradientStop} - Used to define a color within a \l {Gradient} -\o \l {SystemPalette} - Provides access to the Qt palettes -\o \l {Canvas} - Provides a 2D canvas element +\li \l {Rectangle} - A rectangle element +\li \l {Image} - For incorporating bitmaps into a scene +\li \l {BorderImage} - Allows the use of images as borders +\li \l {AnimatedImage} - For playing animations stored in a series of frames +\li \l {Gradient} - For defining a color gradient +\li \l {GradientStop} - Used to define a color within a \l {Gradient} +\li \l {SystemPalette} - Provides access to the Qt palettes +\li \l {Canvas} - Provides a 2D canvas element \endlist \section1 Text Handling \list -\o \l {Text} - For inserting formatted text into a scene -\o \l {TextInput} - Captures user key input -\o \l {TextEdit} - Displays multiple lines of editable formatted text -\o \l {IntValidator} - Validates values as integers -\o \l {DoubleValidator} - Validates real values -\o \l {RegExpValidator} - Validator for string regular expressions -\o \l {FontLoader} - Loads fonts by name or URL +\li \l {Text} - For inserting formatted text into a scene +\li \l {TextInput} - Captures user key input +\li \l {TextEdit} - Displays multiple lines of editable formatted text +\li \l {IntValidator} - Validates values as integers +\li \l {DoubleValidator} - Validates real values +\li \l {RegExpValidator} - Validator for string regular expressions +\li \l {FontLoader} - Loads fonts by name or URL \endlist \section1 Mouse and Interaction Area \list -\o \l {MouseArea} - Sets up an area for mouse interaction -\o \l {Keys} - Provides components with attached properties to handle key input. -\o \l {FocusScope} - Element that mediate keyboard focus changes -\o \l {Flickable} - Provides a surface that can be "flicked" -\o \l {Flipable} - Provides a surface that produces "flipping" effects -\o \l {PinchArea} - Enables simple pinch gesture handling -\o \l {MultiPointTouchArea} - Enables handling of multiple touch points +\li \l {MouseArea} - Sets up an area for mouse interaction +\li \l {Keys} - Provides components with attached properties to handle key input. +\li \l {FocusScope} - Element that mediate keyboard focus changes +\li \l {Flickable} - Provides a surface that can be "flicked" +\li \l {Flipable} - Provides a surface that produces "flipping" effects +\li \l {PinchArea} - Enables simple pinch gesture handling +\li \l {MultiPointTouchArea} - Enables handling of multiple touch points \endlist \section1 Positioners and Repeater \list -\o \l {Column} - Arranges its children vertically -\o \l {Row} - Arranges its children horizontally -\o \l {Grid} - Positions its children in a grid -\o \l {Flow} - Positions its children with wrapping support -\o \l {Repeater} - Uses a model to create multiple components +\li \l {Column} - Arranges its children vertically +\li \l {Row} - Arranges its children horizontally +\li \l {Grid} - Positions its children in a grid +\li \l {Flow} - Positions its children with wrapping support +\li \l {Repeater} - Uses a model to create multiple components \endlist \section1 Transformations \list -\o \l {Scale} - Assigns item scaling behaviors -\o \l {Rotation} - Assigns item rotation behaviors -\o \l {Translate} - Assigns item translation behaviors +\li \l {Scale} - Assigns item scaling behaviors +\li \l {Rotation} - Assigns item rotation behaviors +\li \l {Translate} - Assigns item translation behaviors \endlist \section1 States \list -\o \l {State} - Defines sets of configurations of objects and properties -\o \l {PropertyChanges} - Describes property changes within a state -\o \l {StateGroup} - Contains a set of states and state transitions -\o \l {StateChangeScript} - Allows script binding in a state -\o \l {ParentChange} - Re-parent an Item in a state change -\o \l {AnchorChanges} - Change the anchors of an item in a state +\li \l {State} - Defines sets of configurations of objects and properties +\li \l {PropertyChanges} - Describes property changes within a state +\li \l {StateGroup} - Contains a set of states and state transitions +\li \l {StateChangeScript} - Allows script binding in a state +\li \l {ParentChange} - Re-parent an Item in a state change +\li \l {AnchorChanges} - Change the anchors of an item in a state \endlist \section1 Animation and Transitions \list -\o \l {Transition} - Animates transitions during state changes -\o \l {SequentialAnimation} - Runs animations sequentially -\o \l {ParallelAnimation} - Runs animations in parallel -\o \l {Behavior} - Specifies a default animation for property changes -\o \l {PropertyAction} - Sets immediate property changes during animation -\o \l {PauseAnimation} - Introduces a pause in an animation -\o \l {SmoothedAnimation} - Allows a property to smoothly track a value -\o \l {SpringAnimation} - Allows a property to track a value in a spring-like motion -\o \l {ScriptAction} - Runs scripts during an animation +\li \l {Transition} - Animates transitions during state changes +\li \l {SequentialAnimation} - Runs animations sequentially +\li \l {ParallelAnimation} - Runs animations in parallel +\li \l {Behavior} - Specifies a default animation for property changes +\li \l {PropertyAction} - Sets immediate property changes during animation +\li \l {PauseAnimation} - Introduces a pause in an animation +\li \l {SmoothedAnimation} - Allows a property to smoothly track a value +\li \l {SpringAnimation} - Allows a property to track a value in a spring-like motion +\li \l {ScriptAction} - Runs scripts during an animation \endlist Elements that animate properties based on data types \list -\o \l {PropertyAnimation} - Animates property changes -\o \l {NumberAnimation} - Animates properties of type qreal -\o \l {Vector3dAnimation} - Animates properties of type QVector3d -\o \l {ColorAnimation} - Animates color changes -\o \l {RotationAnimation} - Animates rotations -\o \l {ParentAnimation} - Animates parent changes -\o \l {AnchorAnimation} - Animates anchor changes -\o \l {PathAnimation} - Animates position along a path +\li \l {PropertyAnimation} - Animates property changes +\li \l {NumberAnimation} - Animates properties of type qreal +\li \l {Vector3dAnimation} - Animates properties of type QVector3d +\li \l {ColorAnimation} - Animates color changes +\li \l {RotationAnimation} - Animates rotations +\li \l {ParentAnimation} - Animates parent changes +\li \l {AnchorAnimation} - Animates anchor changes +\li \l {PathAnimation} - Animates position along a path \endlist Elements that provide lower-level animation control \list -\o \l {PathInterpolator} - Allows manual animation along a path -\o \l {AnimationController} - Allows manual control of animation progress +\li \l {PathInterpolator} - Allows manual animation along a path +\li \l {AnimationController} - Allows manual control of animation progress \endlist \section1 Models and Data Handling \list -\o \l {QtQuick2::ListModel}{ListModel} - Defines a list of data -\o \l {QtQuick2::ListElement}{ListElement} - Defines a data item in a \l {QtQuick2::ListModel}{ListModel} -\o \l {VisualItemModel} - Contains items that already defines its own visual delegate -\o \l {VisualDataModel} - Encapsulates a model and a delegate -\o \l {XmlListModel} - Specifies a model using XPath expressions -\o \l {XmlRole} - Specifies a role for an \l {XmlListModel} -\o \l {Binding} - Binds any value to any property -\o \l {Package} - Collection that enables sharing of items within different views +\li \l {QtQuick2::ListModel}{ListModel} - Defines a list of data +\li \l {QtQuick2::ListElement}{ListElement} - Defines a data item in a \l {QtQuick2::ListModel}{ListModel} +\li \l {VisualItemModel} - Contains items that already defines its own visual delegate +\li \l {VisualDataModel} - Encapsulates a model and a delegate +\li \l {XmlListModel} - Specifies a model using XPath expressions +\li \l {XmlRole} - Specifies a role for an \l {XmlListModel} +\li \l {Binding} - Binds any value to any property +\li \l {Package} - Collection that enables sharing of items within different views \endlist \section1 Views \list -\o \l {ListView} - Provides a list visualization of a model -\o \l {GridView} - Provides a grid visualization of a model -\o \l {PathView} - Visualizes a model's contents along a path. See \l {Path Definition}{Path Elements} for more information. +\li \l {ListView} - Provides a list visualization of a model +\li \l {GridView} - Provides a grid visualization of a model +\li \l {PathView} - Visualizes a model's contents along a path. See \l {Path Definition}{Path Elements} for more information. \endlist \section1 Path Definition \list -\o \l {Path} - Defines a path used by \l {PathView} -\o \l {PathLine} - Defines a line in \l {Path} -\o \l {PathQuad} - Defines a quadratic Bezier curve in a \l {Path} -\o \l {PathCubic} - Defines a cubic Bezier curve in a \l {Path} -\o \l {PathArc} - Defines an arc in a \l {Path} -\o \l {PathCurve} - Defines a point on a Catmull-Rom curve in a \l {Path} -\o \l {PathSvg} - Defines a sub-path specified as a SVG path data string in a \l {Path} -\o \l {PathAttribute} - Allows the setting of attributes along a \l {Path} -\o \l {PathPercent} - Modifies the item distribution along a \l {Path} +\li \l {Path} - Defines a path used by \l {PathView} +\li \l {PathLine} - Defines a line in \l {Path} +\li \l {PathQuad} - Defines a quadratic Bezier curve in a \l {Path} +\li \l {PathCubic} - Defines a cubic Bezier curve in a \l {Path} +\li \l {PathArc} - Defines an arc in a \l {Path} +\li \l {PathCurve} - Defines a point on a Catmull-Rom curve in a \l {Path} +\li \l {PathSvg} - Defines a sub-path specified as a SVG path data string in a \l {Path} +\li \l {PathAttribute} - Allows the setting of attributes along a \l {Path} +\li \l {PathPercent} - Modifies the item distribution along a \l {Path} \endlist \section1 Utility \list -\o \l {Connections} - Explicitly connects signals and signal handlers -\o \l {Timer} - Provides timed triggers -\o \l {QmlGlobalQtObject}{Qt} - The QML global Qt object provides useful enums and functions from Qt. -\o \l {WorkerScript} - Enables the use of threads in QML -\o \l {Loader} - Controls the loading of items or components +\li \l {Connections} - Explicitly connects signals and signal handlers +\li \l {Timer} - Provides timed triggers +\li \l {QmlGlobalQtObject}{Qt} - The QML global Qt object provides useful enums and functions from Qt. +\li \l {WorkerScript} - Enables the use of threads in QML +\li \l {Loader} - Controls the loading of items or components \endlist \section1 Graphical Effects \list -\o \l {ShaderEffect} - Allows GLSL shaders to be used as graphical effects -\o \l {ShaderEffectSource} - Usable as a texture in ShaderEffect -\o \l {GridMesh} - Generates a gird mesh of vertices for use by ShaderEffect -\o The \l{QtQuick.Particles 2} module provides a set of Particle System elements for QtQuick 2 +\li \l {ShaderEffect} - Allows GLSL shaders to be used as graphical effects +\li \l {ShaderEffectSource} - Usable as a texture in ShaderEffect +\li \l {GridMesh} - Generates a gird mesh of vertices for use by ShaderEffect +\li The \l{QtQuick.Particles 2} module provides a set of Particle System elements for QtQuick 2 \endlist \section1 Accessibility \list -\o \l {Accessible} - Attached property to make components accessible +\li \l {Accessible} - Attached property to make components accessible \endlist */ diff --git a/doc/src/qtquick2/focus.qdoc b/doc/src/qtquick2/focus.qdoc index e2c4c79d3c..3528169995 100644 --- a/doc/src/qtquick2/focus.qdoc +++ b/doc/src/qtquick2/focus.qdoc @@ -34,7 +34,7 @@ When a key is pressed or released, a key event is generated and delivered to the focused QML \l Item. To facilitate the construction of reusable components and to address some of the cases unique to fluid user interfaces, the QML items add aged -\i scope based extension to Qt's traditional keyboard focus model. +\e scope based extension to Qt's traditional keyboard focus model. \tableofcontents @@ -42,13 +42,13 @@ and to address some of the cases unique to fluid user interfaces, the QML items When the user presses or releases a key, the following occurs: \list 1 -\o Qt receives the key action and generates a key event. -\o If the Qt widget containing the \l QQuickView has focus, the key event +\li Qt receives the key action and generates a key event. +\li If the Qt widget containing the \l QQuickView has focus, the key event is delivered to it. Otherwise, regular Qt key handling continues. -\o The key event is delivered by the scene to the QML \l Item with -\i {active focus}. If no Item has active focus, the key event is +\li The key event is delivered by the scene to the QML \l Item with +\e {active focus}. If no Item has active focus, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues. -\o If the QML Item with active focus accepts the key event, propagation +\li If the QML Item with active focus accepts the key event, propagation stops. Otherwise the event is "bubbled up", by recursively passing it to each Item's parent until either the event is accepted, or the root Item is reached. @@ -59,7 +59,7 @@ item and thus subsequently be ignored. \snippet doc/src/snippets/qml/focus/rectangle.qml simple key event \snippet doc/src/snippets/qml/focus/rectangle.qml simple key event end -\o If the root \l Item is reached, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues. +\li If the root \l Item is reached, the key event is \l {QEvent::ignore()}{ignored} and regular Qt key handling continues. \endlist @@ -119,7 +119,7 @@ the focus, but it cannot control the focus when it is imported or reused. Likewise, the \c window component does not have the ability to know if its imported components are requesting the focus. -To solve this problem, the QML introduces a concept known as a \i {focus scope}. +To solve this problem, the QML introduces a concept known as a \e {focus scope}. For existing Qt users, a focus scope is like an automatic focus proxy. A focus scope is created by declaring the \l FocusScope element. @@ -131,13 +131,13 @@ visual result shown. \image declarative-qmlfocus3.png -Conceptually \i {focus scopes} are quite simple. +Conceptually \e {focus scopes} are quite simple. \list -\o Within each focus scope one element may have \c {Item::focus} set to +\li Within each focus scope one element may have \c {Item::focus} set to \c true. If more than one \l Item has the \c focus property set, the last element to set the \c focus will have the focus and the others are unset, similar to when there are no focus scopes. -\o When a focus scope receives active focus, the contained element with +\li When a focus scope receives active focus, the contained element with \c focus set (if any) also gets the active focus. If this element is also a \l FocusScope, the proxying behavior continues. Both the focus scope and the sub-focused item will have \c activeFocus property set. diff --git a/doc/src/qtquick2/modelview.qdoc b/doc/src/qtquick2/modelview.qdoc index 5d799027ad..0c66a7810b 100644 --- a/doc/src/qtquick2/modelview.qdoc +++ b/doc/src/qtquick2/modelview.qdoc @@ -30,7 +30,7 @@ \brief how to display and form data in QML Simply put, applications need to form data and display the data. QML has the -notion of \i models, \i views, and \i delegates to display data. They modularize +notion of \e models, \e views, and \e delegates to display data. They modularize the visualization of data in order to give the developer or designer control over the different aspects of the data. A developer can swap a list view with a grid view with little changes to the data. Similarly, encapsulating an instance @@ -39,11 +39,11 @@ handle the data. \image modelview-overview.png \list -\o \bold Model - contains the data and its structure. There are several QML +\li \b Model - contains the data and its structure. There are several QML elements for creating models. -\o \bold View - a container that displays the data. The view might +\li \b View - a container that displays the data. The view might display the data in a list or a grid. -\o \bold Delegate - dictates how the data should appear in the view. +\li \b Delegate - dictates how the data should appear in the view. The delegate takes each data in the model and encapsulates it. The data is accessible through the delegate. \endlist @@ -61,9 +61,9 @@ To visualize data, bind the view's \c model property to a model and the graphical elements: \list - \o \l{ListView} - arranges items in a horizontal or vertical list - \o \l{GridView} - arranges items in a grid within the available space - \o \l{PathView} - arranges items on a path + \li \l{ListView} - arranges items in a horizontal or vertical list + \li \l{GridView} - arranges items in a grid within the available space + \li \l{PathView} - arranges items on a path \endlist These elements have properties and behaviors exclusive to each element. @@ -71,7 +71,7 @@ To visualize data, bind the view's \c model property to a model and the \section2 Decorating Views - Views allow visual customization through \i decoration properties such as + Views allow visual customization through \e decoration properties such as the \c header, \c footer, and \c section properties. By binding an object, usually another visual object, to these properties, the views are decoratable. A footer may include a \l Rectangle element showcasing borders @@ -104,7 +104,7 @@ To visualize data, bind the view's \c model property to a model and the \section2 ListView Sections - \l {ListView} contents may be grouped into \i sections, where related list + \l {ListView} contents may be grouped into \e sections, where related list items are labeled according to their sections. Further, the sections may be decorated with \l{qml-view-delegate}{delegates}. @@ -125,7 +125,7 @@ To visualize data, bind the view's \c model property to a model and the \keyword qml-view-delegate \section1 View Delegates - Views need a \i delegate to visually represent an item in a list. A view will + Views need a \e delegate to visually represent an item in a list. A view will visualize each item list according to the template defined by the delegate. Items in a model are accessible through the \c index property as well as the item's properties. @@ -146,9 +146,9 @@ To visualize data, bind the view's \c model property to a model and the properties of each of the views. Similarly, it might be of interest to access or show some properties of the model. - In the following example, the delegate shows the property \i{language} of + In the following example, the delegate shows the property \e{language} of the model, and the color of one of the fields depends on the property - \i{fruit_color} of the view. + \e{fruit_color} of the view. \snippet doc/src/snippets/qml/models/views-models-delegates.qml rectangle @@ -156,21 +156,21 @@ To visualize data, bind the view's \c model property to a model and the \section1 Models Data is provided to the delegate via named data roles which the delegate may - bind to. Here is a ListModel with two roles, \i type and \i age, and a + bind to. Here is a ListModel with two roles, \e type and \e age, and a ListView with a delegate that binds to these roles to display their values: \snippet doc/src/snippets/qml/qml-data-models/listmodel-listview.qml document If there is a naming clash between the model's properties and the delegate's - properties, the roles can be accessed with the qualified \i model name - instead. For example, if a \l Text element had \i type or \i age properties, + properties, the roles can be accessed with the qualified \e model name + instead. For example, if a \l Text element had \e type or \e age properties, the text in the above example would display those property values instead of - the \i type and \i age values from the model item. In this case, the + the \e type and \e age values from the model item. In this case, the properties could have been referenced as \c model.type and \c model.age instead to ensure the delegate displays the property values from the model item. - A special \i index role containing the index of the item in the model is + A special \e index role containing the index of the item in the model is also available to the delegate. Note this index is set to -1 if the item is removed from the model. If you bind to the index role, be sure that the logic accounts for the possibility of index being -1, i.e. that the item is @@ -179,9 +179,9 @@ To visualize data, bind the view's \c model property to a model and the attached property.) Models that do not have named roles (such as the ListModel shown - below) will have the data provided via the \i modelData role. The \i + below) will have the data provided via the \e modelData role. The \e modelData role is also provided for models that have only one role. In this - case the \i modelData role contains the same data as the named role. + case the \e modelData role contains the same data as the named role. QML provides several types of data models among the built-in set of QML elements. In addition, models can be created with Qt C++ and then made @@ -199,7 +199,7 @@ To visualize data, bind the view's \c model property to a model and the \snippet doc/src/snippets/qml/qml-data-models/listelements.qml model - The above model has two roles, \i name and \i cost. These can be bound + The above model has two roles, \e name and \e cost. These can be bound to by a ListView delegate, for example: \snippet doc/src/snippets/qml/qml-data-models/listelements.qml view @@ -214,7 +214,7 @@ To visualize data, bind the view's \c model property to a model and the \dots \snippet doc/src/snippets/qml/qml-data-models/dynamic-listmodel.qml mouse area - When the MouseArea is clicked, \c fruitModel will have two roles, \i cost and \i name. + When the MouseArea is clicked, \c fruitModel will have two roles, \e cost and \e name. Even if subsequent roles are added, only the first two will be handled by views using the model. To reset the roles available in the model, call ListModel::clear(). @@ -229,7 +229,7 @@ To visualize data, bind the view's \c model property to a model and the \endcode - The following model has three roles, \i title, \i link and \i description: + The following model has three roles, \e title, \e link and \e description: \qml XmlListModel { id: feedModel @@ -289,9 +289,9 @@ To visualize data, bind the view's \c model property to a model and the An object instance can be used to specify a model with a single object element. The properties of the object are provided as roles. - The example below creates a list with one item, showing the color of the \i - myText text. Note the use of the fully qualified \i model.color property to - avoid clashing with \i color property of the Text element in the delegate. + The example below creates a list with one item, showing the color of the \e + myText text. Note the use of the fully qualified \e model.color property to + avoid clashing with \e color property of the Text element in the delegate. \qml Rectangle { diff --git a/doc/src/qtquick2/mouseevents.qdoc b/doc/src/qtquick2/mouseevents.qdoc index e452611416..1638311d0c 100644 --- a/doc/src/qtquick2/mouseevents.qdoc +++ b/doc/src/qtquick2/mouseevents.qdoc @@ -36,8 +36,8 @@ \section1 Mouse Elements \list -\o \l{MouseArea} Element -\o \l{MouseEvent} Object +\li \l{MouseArea} Element +\li \l{MouseEvent} Object \endlist \section1 Mouse Event Handling @@ -65,15 +65,15 @@ mouse events. The \l MouseArea element documentation describes these gestures in greater detail: \list -\o canceled -\o clicked -\o doubleClicked -\o entered -\o exited -\o positionChanged -\o pressAndHold -\o pressed -\o released +\li canceled +\li clicked +\li doubleClicked +\li entered +\li exited +\li positionChanged +\li pressAndHold +\li pressed +\li released \endlist These signals have signal handlers that are invoked when the signals are emitted. diff --git a/doc/src/qtquick2/positioners.qdoc b/doc/src/qtquick2/positioners.qdoc index 55be7087fd..138bb8334f 100644 --- a/doc/src/qtquick2/positioners.qdoc +++ b/doc/src/qtquick2/positioners.qdoc @@ -44,10 +44,10 @@ A set of standard positioners are provided in the basic set of Qt Quick graphical elements: \list -\o \l{#Column}{Column} arranges its children in a column -\o \l{#Row}{Row} arranges its children in a row -\o \l{#Grid}{Grid} arranges its children in a grid -\o \l{#Flow}{Flow} arranges its children like words on a page +\li \l{#Column}{Column} arranges its children in a column +\li \l{#Row}{Row} arranges its children in a row +\li \l{#Grid}{Grid} arranges its children in a grid +\li \l{#Flow}{Flow} arranges its children like words on a page \endlist \section2 Column diff --git a/doc/src/qtquick2/qmltexthandling.qdoc b/doc/src/qtquick2/qmltexthandling.qdoc index 6e6b2a4c6b..077671ef5f 100644 --- a/doc/src/qtquick2/qmltexthandling.qdoc +++ b/doc/src/qtquick2/qmltexthandling.qdoc @@ -37,16 +37,16 @@ \section1 Text Elements \list -\o \l{Text} -\o \l{TextInput} -\o \l{TextEdit} +\li \l{Text} +\li \l{TextInput} +\li \l{TextEdit} \endlist \section1 Validators \list -\o \l{IntValidator} -\o \l{DoubleValidator} -\o \l{RegExpValidator} +\li \l{IntValidator} +\li \l{DoubleValidator} +\li \l{RegExpValidator} \endlist \section1 Displaying Text in QML diff --git a/doc/src/qtquick2/qtquick-intro.qdoc b/doc/src/qtquick2/qtquick-intro.qdoc index 9eebb0bddc..0fcf4ef603 100644 --- a/doc/src/qtquick2/qtquick-intro.qdoc +++ b/doc/src/qtquick2/qtquick-intro.qdoc @@ -100,23 +100,23 @@ extendibility and openness, while aiming to lower the barrier of entry for newcomers to Qt Quick and Qt. The key features of Qt Creator allow UI designers and developers to accomplish the following tasks: \list -\o Get started with Qt Quick application development quickly and easily with +\li Get started with Qt Quick application development quickly and easily with examples, tutorials, and project wizards. -\o Design application user interface with the integrated editor, Qt Quick +\li Design application user interface with the integrated editor, Qt Quick Designer, or use graphics software to design the user interface and use scripts to export the design to Qt Quick Designer. -\o Develop applications with the advanced code editor that provides new powerful +\li Develop applications with the advanced code editor that provides new powerful features for completing code snippets, refactoring code, and viewing the element hierarchy of QML files. -\o Build and deploy Qt Quick applications that target multiple desktop and +\li Build and deploy Qt Quick applications that target multiple desktop and mobile platforms, such as Microsoft Windows, Mac OS X, Linux, and Maemo. -\o Debug JavaScript functions and execute JavaScript expressions in the current +\li Debug JavaScript functions and execute JavaScript expressions in the current context, and inspect QML at runtime to explore the object structure, debug animations, and inspect colors. -\o Deploy applications to mobile devices and create application installation +\li Deploy applications to mobile devices and create application installation packages for Maemo devices that can be published in the Ovi Store and other channels. -\o Easily access information with the integrated context-sensitive Qt Help +\li Easily access information with the integrated context-sensitive Qt Help system. \endlist @@ -138,6 +138,6 @@ The \l {Qt Quick Code Samples} page has a gallery of QML applications. \section1 License Information \list -\o \l{Qt Quick Licensing Information} +\li \l{Qt Quick Licensing Information} \endlist */ diff --git a/doc/src/qtquick2/states.qdoc b/doc/src/qtquick2/states.qdoc index 622a1619b0..cdc7bcd5da 100644 --- a/doc/src/qtquick2/states.qdoc +++ b/doc/src/qtquick2/states.qdoc @@ -34,31 +34,31 @@ \target qmlstates \section1 States Elements \list -\o \l State -\o \l PropertyChanges -\o \l StateGroup -\o \l StateChangeScript -\o \l ParentChange -\o \l AnchorChanges +\li \l State +\li \l PropertyChanges +\li \l StateGroup +\li \l StateChangeScript +\li \l ParentChange +\li \l AnchorChanges \endlist -Many user interface designs are \i state driven; interfaces have configurations +Many user interface designs are \e state driven; interfaces have configurations that differ depending on the current state. For example, a traffic signal will configure its flags or lights depending on its state. While in the signal's \c stop state, a red light will turn on while the yellow and the green lights will turn off. In the \c caution state, the yellow light is on while the other lights are turned off. -In QML, \i states are a set of property configurations defined in a \l State +In QML, \e states are a set of property configurations defined in a \l State element. Different configurations could, for example: \list -\o Show some UI elements and hide others -\o Present different available actions to the user -\o Start, stop, or pause animations -\o Execute some script required in the new state -\o Change a property value for a particular item -\o Show a different view or screen +\li Show some UI elements and hide others +\li Present different available actions to the user +\li Start, stop, or pause animations +\li Execute some script required in the new state +\li Change a property value for a particular item +\li Show a different view or screen \endlist All \l {Item}-based objects have a \c state property, and can specify additional @@ -94,15 +94,15 @@ assigning a different state whenever the signal receives a mouse click. The State element is not limited to performing modifications on property values. It can also: \list -\o Run some script using \l StateChangeScript -\o Override an existing signal handler for an object using \l PropertyChanges -\o Re-parent an \l Item using \l ParentChange -\o Modify anchor values using \l AnchorChanges +\li Run some script using \l StateChangeScript +\li Override an existing signal handler for an object using \l PropertyChanges +\li Re-parent an \l Item using \l ParentChange +\li Modify anchor values using \l AnchorChanges \endlist \section1 The Default State -Every \l Item based component has a \c state property and a \i{default state}. +Every \l Item based component has a \c state property and a \e{default state}. The default state is the empty string (\c{""}) and contains all of an item's initial property values. The default state is useful for managing property values before state changes. Setting the \c state property to an empty string @@ -141,13 +141,13 @@ for the engine to fast forward and rewind a state (that is, internally set and u before it is finally applied. The process is as follows: \list 1 -\o The state is fast forwarded to determine the complete set of end values. -\o The state is rewound. -\o The state is fully applied, with transitions. +\li The state is fast forwarded to determine the complete set of end values. +\li The state is rewound. +\li The state is fully applied, with transitions. \endlist In some cases this may cause unintended behavior. For example, a state that changes -a view's \i model or a Loader's \i sourceComponent will set these properties +a view's \e model or a Loader's \e sourceComponent will set these properties multiple times (to apply, rewind, and then reapply), which can be relatively expensive. State fast forwarding should be considered an implementation detail, diff --git a/doc/src/qtquick2/writingcomponents.qdoc b/doc/src/qtquick2/writingcomponents.qdoc index 31267cf20c..864f2d81ea 100644 --- a/doc/src/qtquick2/writingcomponents.qdoc +++ b/doc/src/qtquick2/writingcomponents.qdoc @@ -62,8 +62,8 @@ named \c Button.qml, the component is referred to as \c Button: \table \row -\o \snippet doc/src/snippets/qml/qml-extending-types/components/application.qml 0 -\o \image qml-extending-types.png +\li \snippet doc/src/snippets/qml/qml-extending-types/components/application.qml 0 +\li \image qml-extending-types.png \endtable The root object in \c Button.qml defines the attributes that are available to users of the @@ -83,11 +83,11 @@ To write a useful component, it is generally necessary to provide it with custom communicate specific data. This is achieved by adding the following attributes to your components: \list -\o \bold Properties that can be accessed externally to modify an object (for example, \l Item has +\li \b Properties that can be accessed externally to modify an object (for example, \l Item has \l {Item::}{width} and \l {Item::}{height} properties) and used in \l {Property Binding} -\o \bold Methods of JavaScript code can be invoked internally or externally (for example, +\li \b Methods of JavaScript code can be invoked internally or externally (for example, \l Animation has a \l {Animation::}{start()} method) -\o \bold Signals to notify other objects when an event has occurred (for example, MouseArea has a +\li \b Signals to notify other objects when an event has occurred (for example, MouseArea has a \c clicked signal) \endlist @@ -119,8 +119,8 @@ an \c ImageViewer object and read or modify the \c currentImage value: \table \row -\o \snippet doc/src/snippets/qml/qml-extending-types/properties/ImageViewer.qml 0 -\o \snippet doc/src/snippets/qml/qml-extending-types/properties/application.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/properties/ImageViewer.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/properties/application.qml 0 \endtable It is optional for a property to have a default value. The default value is a convenient shortcut, and is @@ -146,16 +146,16 @@ A number of property types are supported by default. These are listed in the tab with their default values and the corresponding C++ type: \table -\header \o QML Type Name \o Default value \o C++ Type Name -\row \o \l int \o 0 \o int -\row \o \l bool \o \c false \o bool -\row \o \l double \o 0.0 \o double -\row \o \l real \o 0.0 \o double -\row \o \l string \o "" (empty string) \o QString -\row \o \l url \o "" (empty url) \o QUrl -\row \o \l color \o #000000 (black) \o QColor -\row \o \l date \o \c undefined \o QDateTime -\row \o \l variant \o \c undefined \o QVariant +\header \li QML Type Name \li Default value \li C++ Type Name +\row \li \l int \li 0 \li int +\row \li \l bool \li \c false \li bool +\row \li \l double \li 0.0 \li double +\row \li \l real \li 0.0 \li double +\row \li \l string \li "" (empty string) \li QString +\row \li \l url \li "" (empty url) \li QUrl +\row \li \l color \li #000000 (black) \li QColor +\row \li \l date \li \c undefined \li QDateTime +\row \li \l variant \li \c undefined \li QVariant \endtable QML object types can also be used as property types. This includes @@ -290,8 +290,8 @@ been changed to an alias to the child \l Image object: \table \row -\o \snippet doc/src/snippets/qml/qml-extending-types/properties/alias/ImageViewer.qml 0 -\o \snippet doc/src/snippets/qml/qml-extending-types/properties/alias/application.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/properties/alias/ImageViewer.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/properties/alias/application.qml 0 \endtable Instead of being limited to setting the \l Image source, \c application.qml can now directly @@ -411,9 +411,9 @@ The signal hander is named \c on, with the first letter of the signa cased. The above example item would now have the following signal handlers: \list -\o onClicked -\o onHovered -\o onPerformAction +\li onClicked +\li onHovered +\li onPerformAction \endlist To emit a signal, simply invoke it in the same way as a method. Below left, when the \l MouseArea is @@ -422,8 +422,8 @@ signal is received by \c application.qml through an \c onButtonClicked signal ha \table \row -\o \snippet doc/src/snippets/qml/qml-extending-types/signals/basic.qml 0 -\o \snippet doc/src/snippets/qml/qml-extending-types/signals/no-parameters.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/signals/basic.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/signals/no-parameters.qml 0 \endtable If the signal has parameters, they are accessible by parameter name in the signal handler. @@ -431,8 +431,8 @@ In the example below, \c buttonClicked is emitted with \c xPos and \c yPos param \table \row -\o \snippet doc/src/snippets/qml/qml-extending-types/signals/Button.qml 0 -\o \snippet doc/src/snippets/qml/qml-extending-types/signals/parameters.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/signals/Button.qml 0 +\li \snippet doc/src/snippets/qml/qml-extending-types/signals/parameters.qml 0 \endtable diff --git a/doc/src/whatsnew.qdoc b/doc/src/whatsnew.qdoc index c791e72c25..1997a42a6b 100644 --- a/doc/src/whatsnew.qdoc +++ b/doc/src/whatsnew.qdoc @@ -40,10 +40,10 @@ QtQuick 2 is based on an OpenGL scenegraph. The following classes replace their equivalents in QtQuick 1: \list -\o QQuickView -\o QQuickCanvas -\o QQuickItem -\o QQuickPaintedItem +\li QQuickView +\li QQuickCanvas +\li QQuickItem +\li QQuickPaintedItem \endlist \section2 QML Engine/Language Improvements @@ -100,7 +100,7 @@ You can still ignore these events in the handler to let them pass through. This behavior is triggered with the new property propagateComposedEvents. The Binding element can now be used as a value source, and will also restore any previously -set binding when its \i when clause becomes false. +set binding when its \e when clause becomes false. Flickable: added dragging, draggingHorizontally and draggingVerically properties. Added topMargin, bottomMargin, leftMargin, rightMargin, xOrigin, yOrigin properties. @@ -114,8 +114,8 @@ of integers. Positioner (Row, Column, Grid, Flow) improvements: \list -\o Transitions used for \c add and \c move now have improved features: they can access a ViewTransition attached property (see the ViewTransition documentation for examples) and can now animate arbitrary item properties (instead of being restricted to animating an item's position). -\o Items in a positioner now have attached properties that can be used to determine a subitem's location: Positioner.index, Positioner.isFirstItem, Positioner.isLastItem. +\li Transitions used for \c add and \c move now have improved features: they can access a ViewTransition attached property (see the ViewTransition documentation for examples) and can now animate arbitrary item properties (instead of being restricted to animating an item's position). +\li Items in a positioner now have attached properties that can be used to determine a subitem's location: Positioner.index, Positioner.isFirstItem, Positioner.isLastItem. \endlist Loader improvements: diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp index d68d7af6d4..294fe184d2 100644 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp +++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp @@ -208,21 +208,21 @@ void QQuickFolderListModelPrivate::_q_sortFinished(const QList &li \e{Elements in the Qt.labs module are not guaranteed to remain compatible in future versions.} - \bold{import Qt.labs.folderlistmodel 1.0} + \b{import Qt.labs.folderlistmodel 1.0} The \l folder property specifies the folder to access. Information about the files and directories in the folder is supplied via the model's interface. Components access names and paths via the following roles: \list - \o \c fileName - \o \c filePath - \o \c fileBaseName - \o \c fileSuffix - \o \c fileSize - \o \c fileModified - \o \c fileAccessed - \o \c fileIsDir + \li \c fileName + \li \c filePath + \li \c fileBaseName + \li \c fileSuffix + \li \c fileSize + \li \c fileModified + \li \c fileAccessed + \li \c fileIsDir \endlist Additionally a file entry can be differentiated from a folder entry via the @@ -493,11 +493,11 @@ void QQuickFolderListModel::componentComplete() The \a sortField property contains field to use for sorting. sortField may be one of: \list - \o Unsorted - no sorting is applied. - \o Name - sort by filename - \o LastModified - sort by time modified - \o Size - sort by file size - \o Type - sort by file type (extension) + \li Unsorted - no sorting is applied. + \li Name - sort by filename + \li LastModified - sort by time modified + \li Size - sort by file size + \li Type - sort by file type (extension) \endlist \sa sortReversed @@ -672,14 +672,14 @@ void QQuickFolderListModel::setShowOnlyReadable(bool on) are available. \list - \o \c fileName - \o \c filePath - \o \c fileBaseName - \o \c fileSuffix - \o \c fileSize - \o \c fileModified - \o \c fileAccessed - \o \c fileIsDir + \li \c fileName + \li \c filePath + \li \c fileBaseName + \li \c fileSuffix + \li \c fileSize + \li \c fileModified + \li \c fileAccessed + \li \c fileIsDir \endlist */ QVariant QQuickFolderListModel::get(int idx, const QString &property) const diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 7c55225ed1..0187d06e6a 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -480,9 +480,9 @@ import QtQuick.LocalStorage 2.0 as LS db = LS.openDatabaseSync(identifier, version, description, estimated_size, callback(db)) \endcode -The above code returns the database identified by \i identifier. If the database does not already exist, it -is created, and the function \i callback is called with the database as a parameter. \i description -and \i estimated_size are written to the INI file (described below), but are otherwise currently +The above code returns the database identified by \e identifier. If the database does not already exist, it +is created, and the function \e callback is called with the database as a parameter. \e description +and \e estimated_size are written to the INI file (described below), but are otherwise currently unused. May throw exception with code property SQLException.DATABASE_ERR, or SQLException.VERSION_ERR. @@ -490,51 +490,51 @@ May throw exception with code property SQLException.DATABASE_ERR, or SQLExceptio When a database is first created, an INI file is also created specifying its characteristics: \table -\header \o \bold {Key} \o \bold {Value} -\row \o Name \o The name of the database passed to \c openDatabase() -\row \o Version \o The version of the database passed to \c openDatabase() -\row \o Description \o The description of the database passed to \c openDatabase() -\row \o EstimatedSize \o The estimated size (in bytes) of the database passed to \c openDatabase() -\row \o Driver \o Currently "QSQLITE" +\header \li \b {Key} \li \b {Value} +\row \li Name \li The name of the database passed to \c openDatabase() +\row \li Version \li The version of the database passed to \c openDatabase() +\row \li Description \li The description of the database passed to \c openDatabase() +\row \li EstimatedSize \li The estimated size (in bytes) of the database passed to \c openDatabase() +\row \li Driver \li Currently "QSQLITE" \endtable This data can be used by application tools. \section3 db.changeVersion(from, to, callback(tx)) -This method allows you to perform a \i{Scheme Upgrade}. +This method allows you to perform a \e{Scheme Upgrade}. -If the current version of \i db is not \i from, then an exception is thrown. +If the current version of \e db is not \e from, then an exception is thrown. -Otherwise, a database transaction is created and passed to \i callback. In this function, -you can call \i executeSql on \i tx to upgrade the database. +Otherwise, a database transaction is created and passed to \e callback. In this function, +you can call \e executeSql on \e tx to upgrade the database. May throw exception with code property SQLException.DATABASE_ERR or SQLException.UNKNOWN_ERR. \section3 db.transaction(callback(tx)) -This method creates a read/write transaction and passed to \i callback. In this function, -you can call \i executeSql on \i tx to read and modify the database. +This method creates a read/write transaction and passed to \e callback. In this function, +you can call \e executeSql on \e tx to read and modify the database. If the callback throws exceptions, the transaction is rolled back. \section3 db.readTransaction(callback(tx)) -This method creates a read-only transaction and passed to \i callback. In this function, -you can call \i executeSql on \i tx to read the database (with SELECT statements). +This method creates a read-only transaction and passed to \e callback. In this function, +you can call \e executeSql on \e tx to read the database (with SELECT statements). \section3 results = tx.executeSql(statement, values) -This method executes a SQL \i statement, binding the list of \i values to SQL positional parameters ("?"). +This method executes a SQL \e statement, binding the list of \e values to SQL positional parameters ("?"). It returns a results object, with the following properties: \table -\header \o \bold {Type} \o \bold {Property} \o \bold {Value} \o \bold {Applicability} -\row \o int \o rows.length \o The number of rows in the result \o SELECT -\row \o var \o rows.item(i) \o Function that returns row \i i of the result \o SELECT -\row \o int \o rowsAffected \o The number of rows affected by a modification \o UPDATE, DELETE -\row \o string \o insertId \o The id of the row inserted \o INSERT +\header \li \b {Type} \li \b {Property} \li \b {Value} \li \b {Applicability} +\row \li int \li rows.length \li The number of rows in the result \li SELECT +\row \li var \li rows.item(i) \li Function that returns row \e i of the result \li SELECT +\row \li int \li rowsAffected \li The number of rows affected by a modification \li UPDATE, DELETE +\row \li string \li insertId \li The id of the row inserted \li INSERT \endtable May throw exception with code property SQLException.DATABASE_ERR, SQLException.SYNTAX_ERR, or SQLException.UNKNOWN_ERR. diff --git a/src/imports/testlib/testcase.qdoc b/src/imports/testlib/testcase.qdoc index d8a20e4fc7..f928cdaa44 100644 --- a/src/imports/testlib/testcase.qdoc +++ b/src/imports/testlib/testcase.qdoc @@ -180,7 +180,7 @@ and mouseMove() methods can be used to simulate mouse events in a similar fashion. - \bold{Note:} keyboard and mouse events can only be delivered once the + \b{Note:} keyboard and mouse events can only be delivered once the main window has been shown. Attempts to deliver events before then will fail. Use the \l when and windowShown properties to track when the main window has been shown. @@ -446,7 +446,7 @@ focused item. If \a delay is larger than 0, the test will wait for \a delay milliseconds. - \bold{Note:} At some point you should release the key using keyRelease(). + \b{Note:} At some point you should release the key using keyRelease(). \sa keyRelease(), keyClick() */ diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp index 1377859b5e..22072dc75a 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp +++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp @@ -909,10 +909,10 @@ QQmlV8Handle QQuickXmlListModel::get(int index) const Specifies the model loading status, which can be one of the following: \list - \o XmlListModel.Null - No XML data has been set for this model. - \o XmlListModel.Ready - The XML data has been loaded into the model. - \o XmlListModel.Loading - The model is in the process of reading and loading XML data. - \o XmlListModel.Error - An error occurred while the model was loading. See errorString() for details + \li XmlListModel.Null - No XML data has been set for this model. + \li XmlListModel.Ready - The XML data has been loaded into the model. + \li XmlListModel.Loading - The model is in the process of reading and loading XML data. + \li XmlListModel.Error - An error occurred while the model was loading. See errorString() for details about the error. \endlist diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5dd8fc8ae9..79100c4394 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -362,10 +362,10 @@ QQmlComponent::~QQmlComponent() \qmlproperty enumeration Component::status This property holds the status of component loading. It can be one of: \list - \o Component.Null - no data is available for the component - \o Component.Ready - the component has been loaded, and can be used to create instances. - \o Component.Loading - the component is currently being loaded - \o Component.Error - an error occurred while loading the component. + \li Component.Null - no data is available for the component + \li Component.Ready - the component has been loaded, and can be used to create instances. + \li Component.Loading - the component is currently being loaded + \li Component.Error - an error occurred while loading the component. Calling errorString() will provide a human-readable description of any errors. \endlist */ @@ -686,9 +686,9 @@ QObject *QQmlComponent::create(QQmlContext *context) When QQmlComponent constructs an instance, it occurs in three steps: \list 1 - \i The object hierarchy is created, and constant values are assigned. - \i Property bindings are evaluated for the the first time. - \i If applicable, QQmlParserStatus::componentComplete() is called on objects. + \li The object hierarchy is created, and constant values are assigned. + \li Property bindings are evaluated for the the first time. + \li If applicable, QQmlParserStatus::componentComplete() is called on objects. \endlist QQmlComponent::beginCreate() differs from QQmlComponent::create() in that it only performs step 1. QQmlComponent::completeCreate() must be called to @@ -1079,13 +1079,13 @@ void QQmlComponent::createObject(QQmlV8Function *args) properties: \list - \i status The status of the incubator. Valid values are Component.Ready, Component.Loading and + \li status The status of the incubator. Valid values are Component.Ready, Component.Loading and Component.Error. - \i object The created object instance. Will only be available once the incubator is in the + \li object The created object instance. Will only be available once the incubator is in the Ready status. - \i onStatusChanged Specifies a callback function to be invoked when the status changes. The + \li onStatusChanged Specifies a callback function to be invoked when the status changes. The status is passed as a parameter to the callback. - \i forceCompletion() Call to complete incubation synchronously. + \li forceCompletion() Call to complete incubation synchronously. \endlist The following example demonstrates how to use an incubator: diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 38acc0b0c3..cbb8430f40 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -329,7 +329,7 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value) /*! Set the \a value of the \a name property on this context. - QQmlContext does \bold not take ownership of \a value. + QQmlContext does \b not take ownership of \a value. */ void QQmlContext::setContextProperty(const QString &name, QObject *value) { diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index d745513ca9..6f832c2b27 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -217,11 +217,11 @@ data types. This is primarily useful when setting the properties of an item when the property has one of the following types: \list -\o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()} -\o \c rect - use \l{Qt::rect()}{Qt.rect()} -\o \c point - use \l{Qt::point()}{Qt.point()} -\o \c size - use \l{Qt::size()}{Qt.size()} -\o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()} +\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()} +\li \c rect - use \l{Qt::rect()}{Qt.rect()} +\li \c point - use \l{Qt::point()}{Qt.point()} +\li \c size - use \l{Qt::size()}{Qt.size()} +\li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()} \endlist There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information. @@ -231,9 +231,9 @@ There are also string based constructors for these types. See \l{qdeclarativebas The Qt object contains several functions for formatting QDateTime, QDate and QTime values. \list - \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)} - \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)} - \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)} + \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)} + \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)} + \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)} \endlist The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}. @@ -245,8 +245,8 @@ items from files or strings. See \l{Dynamic Object Management in QML} for an ove of their use. \list - \o \l{Qt::createComponent()}{object Qt.createComponent(url)} - \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)} + \li \l{Qt::createComponent()}{object Qt.createComponent(url)} + \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)} \endlist */ @@ -262,8 +262,8 @@ of their use. \table \row - \o \c application.active - \o + \li \c application.active + \li This read-only property indicates whether the application is the top-most and focused application, and the user is able to interact with the application. The property is false when the application is in the background, the device keylock or screen @@ -274,8 +274,8 @@ of their use. active. \row - \o \c application.layoutDirection - \o + \li \c application.layoutDirection + \li This read-only property can be used to query the default layout direction of the application. On system start-up, the default layout direction depends on the application's language. The property has a value of \c Qt.RightToLeft in locales @@ -286,15 +286,15 @@ of their use. Possible values are: \list - \o Qt.LeftToRight - Text and graphics elements should be positioned + \li Qt.LeftToRight - Text and graphics elements should be positioned from left to right. - \o Qt.RightToLeft - Text and graphics elements should be positioned + \li Qt.RightToLeft - Text and graphics elements should be positioned from right to left. \endlist \row - \o \c application.inputPanel - \o + \li \c application.inputPanel + \li This read-only property allows access to application's QInputPanel object and all its properties and slots. See the QInputPanel documentation for further details. Deprecated in favor of Qt.InputMethod @@ -326,11 +326,11 @@ Qt.include() returns an object that describes the status of the operation. The a single property, \c {status}, that is set to one of the following values: \table -\header \o Symbol \o Value \o Description -\row \o result.OK \o 0 \o The include completed successfully. -\row \o result.LOADING \o 1 \o Data is being loaded from the network. -\row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url. -\row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code. +\header \li Symbol \li Value \li Description +\row \li result.OK \li 0 \li The include completed successfully. +\row \li result.LOADING \li 1 \li Data is being loaded from the network. +\row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url. +\row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code. An additional \c exception property will be set in this case. \endtable diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index c3d8f0b34f..b69fa5da7a 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -57,10 +57,10 @@ QT_BEGIN_NAMESPACE To write a QML extension plugin: \list - \o Subclass QQmlExtensionPlugin, implement registerTypes() method + \li Subclass QQmlExtensionPlugin, implement registerTypes() method to register types using qmlRegisterType(), and export the class using the Q_EXPORT_PLUGIN2() macro - \o Write an appropriate project file for the plugin - \o Create a \l{Writing a qmldir file}{qmldir file} to describe the plugin + \li Write an appropriate project file for the plugin + \li Create a \l{Writing a qmldir file}{qmldir file} to describe the plugin \endlist QML extension plugins can be used to provide either application-specific or diff --git a/src/qml/qml/qqmlimageprovider.cpp b/src/qml/qml/qqmlimageprovider.cpp index 756b943fc0..d1afa54498 100644 --- a/src/qml/qml/qqmlimageprovider.cpp +++ b/src/qml/qml/qqmlimageprovider.cpp @@ -117,12 +117,12 @@ QImage QQuickTextureFactory::image() const in QML applications. It allows images in QML to be: \list - \o Loaded using QPixmaps rather than actual image files - \o Loaded asynchronously in a separate thread, if imageType() is \l{QQmlImageProvider::ImageType}{ImageType::Image} + \li Loaded using QPixmaps rather than actual image files + \li Loaded asynchronously in a separate thread, if imageType() is \l{QQmlImageProvider::ImageType}{ImageType::Image} \endlist To specify that an image should be loaded by an image provider, use the - \bold {"image:"} scheme for the URL source of the image, followed by the + \b {"image:"} scheme for the URL source of the image, followed by the identifiers of the image provider and the requested image. For example: \qml diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 6e74536fa3..0c1fb3bd93 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -268,9 +268,9 @@ QList QQmlImports::resolvedScripts() const The given (namespace qualified) \a type is resolved to either \list - \o a QQmlImportedNamespace stored at \a ns_return, - \o a QQmlType stored at \a type_return, or - \o a component located at \a url_return. + \li a QQmlImportedNamespace stored at \a ns_return, + \li a QQmlType stored at \a type_return, or + \li a component located at \a url_return. \endlist If any return pointer is 0, the corresponding search is not done. @@ -956,12 +956,12 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, Returns the result of the merge of \a baseName with \a dir and the platform suffix. \table - \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll - \row \i Unix/Linux \i \c .so - \row \i AIX \i \c .a - \row \i HP-UX \i \c .sl, \c .so (HP-UXi) - \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so + \header \li Platform \li Valid suffixes + \row \li Windows \li \c .dll + \row \li Unix/Linux \li \c .so + \row \li AIX \li \c .a + \row \li HP-UX \li \c .sl, \c .so (HP-UXi) + \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so \endtable Version number on unix are ignored. diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index 834d4bbb97..c8413f70ca 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -427,14 +427,14 @@ specified IncubationMode. QQmlIncubator supports three incubation modes: \list -\i Synchronous The creation occurs synchronously. That is, once the +\li Synchronous The creation occurs synchronously. That is, once the QQmlComponent::create() call returns, the incubator will already be in either the Error or Ready state. A synchronous incubator has no real advantage compared to using the synchronous creation methods on QQmlComponent directly, but it may simplify an application's implementation to use the same API for both synchronous and asynchronous creations. -\i Asynchronous (default) The creation occurs asynchronously, assuming a +\li Asynchronous (default) The creation occurs asynchronously, assuming a QQmlIncubatorController is set on the QQmlEngine. The incubator will remain in the Loading state until either the creation is complete or an error @@ -446,7 +446,7 @@ that are slightly off screen while the list is being scrolled. If, during async the object is needed immediately the QQmlIncubator::forceCompletion() method can be called to complete the creation process synchronously. -\i AsynchronousIfNested The creation will occur asynchronously if part of a nested asynchronous +\li AsynchronousIfNested The creation will occur asynchronously if part of a nested asynchronous creation, or synchronously if not. In most scenarios where a QML element or component wants the appearance of a synchronous diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index d684378832..4a4563ccd4 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -1023,13 +1023,13 @@ v8::Handle QQmlLocale::localeCompare(const v8::Arguments &args) Holds the first day of the week according to the current locale. \list - \o Locale.Sunday = 0 - \o Locale.Monday = 1 - \o Locale.Tuesday = 2 - \o Locale.Wednesday = 3 - \o Locale.Thursday = 4 - \o Locale.Friday = 5 - \o Locale.Saturday = 6 + \li Locale.Sunday = 0 + \li Locale.Monday = 1 + \li Locale.Tuesday = 2 + \li Locale.Wednesday = 3 + \li Locale.Thursday = 4 + \li Locale.Friday = 5 + \li Locale.Saturday = 6 \endlist \note that these values match the JS Date API which is different @@ -1062,8 +1062,8 @@ v8::Handle QQmlLocale::localeCompare(const v8::Arguments &args) Holds the text direction of the language: \list - \o Qt.LeftToRight - \o Qt.RightToLeft + \li Qt.LeftToRight + \li Qt.RightToLeft \endlist */ @@ -1084,9 +1084,9 @@ v8::Handle QQmlLocale::localeCompare(const v8::Arguments &args) Returns the currency symbol for the specified \a format: \list - \o Locale.CurrencyIsoCode a ISO-4217 code of the currency. - \o Locale.CurrencySymbol a currency symbol. - \o Locale.CurrencyDisplayName a user readable name of the currency. + \li Locale.CurrencyIsoCode a ISO-4217 code of the currency. + \li Locale.CurrencySymbol a currency symbol. + \li Locale.CurrencyDisplayName a user readable name of the currency. \endlist \sa Number::toLocaleCurrencyString() */ @@ -1115,9 +1115,9 @@ v8::Handle QQmlLocale::localeCompare(const v8::Arguments &args) This property defines which units are used for measurement. \list - \o Locale.MetricSystem This value indicates metric units, such as meters, + \li Locale.MetricSystem This value indicates metric units, such as meters, centimeters and millimeters. - \o Locale.ImperialSystem This value indicates imperial units, such as inches and + \li Locale.ImperialSystem This value indicates imperial units, such as inches and miles. There are several distinct imperial systems in the world; this value stands for the official United States imperial units. \endlist diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp index cc33f387d9..e5d0d708e2 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp @@ -65,12 +65,12 @@ QT_BEGIN_NAMESPACE be created in a different thread: \list - \o The QML engine internally handles all requests, and cleans up any + \li The QML engine internally handles all requests, and cleans up any QNetworkReply objects it creates. Receiving the QNetworkAccessManager::finished() signal in another thread may not provide the receiver with a valid reply object if it has already been deleted. - \o Authentication details provided to QNetworkAccessManager::authenticationRequired() + \li Authentication details provided to QNetworkAccessManager::authenticationRequired() must be provided immediately, so this signal cannot be connected as a Qt::QueuedConnection (or as the default Qt::AutoConnection from another thread). diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 5cbb2f6943..0082d55c48 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -248,14 +248,14 @@ The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes availab This enum describes the status of the data blob. \list -\o Null The blob has not yet been loaded by a QQmlDataLoader -\o Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been +\li Null The blob has not yet been loaded by a QQmlDataLoader +\li Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been invoked or has not yet returned. -\o WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status +\li WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status only occurs after the QQmlDataBlob::setData() callback has been made, and when the blob has outstanding dependencies. -\o Complete The blob's data has been loaded and all dependencies are done. -\o Error An error has been set on this blob. +\li Complete The blob's data has been loaded and all dependencies are done. +\li Error An error has been set on this blob. \endlist */ @@ -265,9 +265,9 @@ dependencies. This enum describes the type of the data blob. \list -\o QmlFile This is a QQmlTypeData -\o JavaScriptFile This is a QQmlScriptData -\o QmldirFile This is a QQmlQmldirData +\li QmlFile This is a QQmlTypeData +\li JavaScriptFile This is a QQmlScriptData +\li QmldirFile This is a QQmlQmldirData \endlist */ @@ -877,9 +877,9 @@ To complete processing, the QQmlDataBlob::done() callback is invoked. done() is one of these three preconditions are met. \list 1 -\o The QQmlDataBlob has no dependencies. -\o The QQmlDataBlob has an error set. -\o All the QQmlDataBlob's dependencies are themselves "done()". +\li The QQmlDataBlob has no dependencies. +\li The QQmlDataBlob has an error set. +\li All the QQmlDataBlob's dependencies are themselves "done()". \endlist Thus QQmlDataBlob::done() will always eventually be called, even if the blob has an error set. diff --git a/src/qml/qml/qquickworkerscript.cpp b/src/qml/qml/qquickworkerscript.cpp index 529f181e7a..e689f9da72 100644 --- a/src/qml/qml/qquickworkerscript.cpp +++ b/src/qml/qml/qquickworkerscript.cpp @@ -640,9 +640,9 @@ void QQuickWorkerScript::setSource(const QUrl &source) types: \list - \o boolean, number, string - \o JavaScript objects and arrays - \o ListModel objects (any other type of QObject* is not allowed) + \li boolean, number, string + \li JavaScript objects and arrays + \li ListModel objects (any other type of QObject* is not allowed) \endlist All objects and arrays are copied to the \c message. With the exception diff --git a/src/qml/qml/v8/qjsengine.cpp b/src/qml/qml/v8/qjsengine.cpp index 3121d1b361..92c968f9aa 100644 --- a/src/qml/qml/v8/qjsengine.cpp +++ b/src/qml/qml/v8/qjsengine.cpp @@ -92,7 +92,7 @@ Q_DECLARE_METATYPE(QList) \section1 Engine Configuration - The globalObject() function returns the \bold {Global Object} + The globalObject() function returns the \b {Global Object} associated with the script engine. Properties of the Global Object are accessible from any script code (i.e. they are global variables). Typically, before evaluating "user" scripts, you will diff --git a/src/qml/qml/v8/qjsvalue.cpp b/src/qml/qml/v8/qjsvalue.cpp index e0a925c3bb..4471e68a61 100644 --- a/src/qml/qml/v8/qjsvalue.cpp +++ b/src/qml/qml/v8/qjsvalue.cpp @@ -426,18 +426,18 @@ quint32 QJSValue::toUInt() const The conversion is performed according to the following table: \table - \header \o Input Type \o Result - \row \o Undefined \o An invalid QVariant. - \row \o Null \o An invalid QVariant. - \row \o Boolean \o A QVariant containing the value of the boolean. - \row \o Number \o A QVariant containing the value of the number. - \row \o String \o A QVariant containing the value of the string. - \row \o QVariant Object \o The result is the QVariant value of the object (no conversion). - \row \o QObject Object \o A QVariant containing a pointer to the QObject. - \row \o Date Object \o A QVariant containing the date value (toDateTime()). - \row \o RegExp Object \o A QVariant containing the regular expression value. - \row \o Array Object \o The array is converted to a QVariantList. Each element is converted to a QVariant, recursively; cyclic references are not followed. - \row \o Object \o The object is converted to a QVariantMap. Each property is converted to a QVariant, recursively; cyclic references are not followed. + \header \li Input Type \li Result + \row \li Undefined \li An invalid QVariant. + \row \li Null \li An invalid QVariant. + \row \li Boolean \li A QVariant containing the value of the boolean. + \row \li Number \li A QVariant containing the value of the number. + \row \li String \li A QVariant containing the value of the string. + \row \li QVariant Object \li The result is the QVariant value of the object (no conversion). + \row \li QObject Object \li A QVariant containing a pointer to the QObject. + \row \li Date Object \li A QVariant containing the date value (toDateTime()). + \row \li RegExp Object \li A QVariant containing the regular expression value. + \row \li Array Object \li The array is converted to a QVariantList. Each element is converted to a QVariant, recursively; cyclic references are not followed. + \row \li Object \li The object is converted to a QVariantMap. Each property is converted to a QVariant, recursively; cyclic references are not followed. \endtable \sa isVariant() @@ -634,13 +634,13 @@ bool QJSValue::equals(const QJSValue& other) const the result depends on the type, as shown in the following table: \table - \header \o Type \o Result - \row \o Undefined \o true - \row \o Null \o true - \row \o Boolean \o true if both values are true, false otherwise - \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise - \row \o String \o true if both values are exactly the same sequence of characters, false otherwise - \row \o Object \o true if both values refer to the same object, false otherwise + \header \li Type \li Result + \row \li Undefined \li true + \row \li Null \li true + \row \li Boolean \li true if both values are true, false otherwise + \row \li Number \li false if either value is NaN (Not-a-Number); true if values are equal, false otherwise + \row \li String \li true if both values are exactly the same sequence of characters, false otherwise + \row \li Object \li true if both values refer to the same object, false otherwise \endtable \sa equals() @@ -737,11 +737,11 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value) delete operator. In particular: \list - \o Non-configurable properties cannot be deleted. - \o This function will return true even if this object doesn't + \li Non-configurable properties cannot be deleted. + \li This function will return true even if this object doesn't have a property of the given \a name (i.e., non-existent properties are "trivially deletable"). - \o If this object doesn't have an own property of the given + \li If this object doesn't have an own property of the given \a name, but an object in the prototype() chain does, the prototype object's property is not deleted, and this function returns true. diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 951bcc5ad3..11a233d093 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -797,54 +797,54 @@ If \a format is not provided, \a dateTime is formatted using \a format should be either: \list -\o One of the Qt::DateFormat enumeration values, such as +\li One of the Qt::DateFormat enumeration values, such as \c Qt.DefaultLocaleShortDate or \c Qt.ISODate -\o A string that specifies the format of the returned string, as detailed below. +\li A string that specifies the format of the returned string, as detailed below. \endlist If \a format specifies a format string, it should use the following expressions to specify the date: \table - \header \i Expression \i Output - \row \i d \i the day as number without a leading zero (1 to 31) - \row \i dd \i the day as number with a leading zero (01 to 31) - \row \i ddd - \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \header \li Expression \li Output + \row \li d \li the day as number without a leading zero (1 to 31) + \row \li dd \li the day as number with a leading zero (01 to 31) + \row \li ddd + \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). - \row \i dddd - \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). + \row \li dddd + \li the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). Uses QDate::longDayName(). - \row \i M \i the month as number without a leading zero (1-12) - \row \i MM \i the month as number with a leading zero (01-12) - \row \i MMM - \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li M \li the month as number without a leading zero (1-12) + \row \li MM \li the month as number with a leading zero (01-12) + \row \li MMM + \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). - \row \i MMMM - \i the long localized month name (e.g. 'January' to 'December'). + \row \li MMMM + \li the long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). - \row \i yy \i the year as two digit number (00-99) - \row \i yyyy \i the year as four digit number + \row \li yy \li the year as two digit number (00-99) + \row \li yyyy \li the year as four digit number \endtable In addition the following expressions can be used to specify the time: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP - \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". - \row \i ap - \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP + \li use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \li ap + \li use am/pm display. \e ap will be replaced by either "am" or "pm". \endtable All other input characters will be ignored. Any sequence of characters that @@ -864,11 +864,11 @@ This \a dateTime value could be passed to \c Qt.formatDateTime(), with the \a format values below to produce the following results: \table - \header \i Format \i Result - \row \i "dd.MM.yyyy" \i 21.05.2001 - \row \i "ddd MMMM d yy" \i Tue May 21 01 - \row \i "hh:mm:ss.zzz" \i 14:13:09.042 - \row \i "h:m:s ap" \i 2:13:9 pm + \header \li Format \li Result + \row \li "dd.MM.yyyy" \li 21.05.2001 + \row \li "ddd MMMM d yy" \li Tue May 21 01 + \row \li "hh:mm:ss.zzz" \li 14:13:09.042 + \row \li "h:m:s ap" \li 2:13:9 pm \endtable \sa Locale @@ -1287,9 +1287,9 @@ v8::Handle qsTrIdNoOp(const v8::Arguments &args) or "C", where: \list - \o language is a lowercase, two-letter, ISO 639 language code, - \o territory is an uppercase, two-letter, ISO 3166 country code, - \o and codeset and modifier are ignored. + \li language is a lowercase, two-letter, ISO 639 language code, + \li territory is an uppercase, two-letter, ISO 3166 country code, + \li and codeset and modifier are ignored. \endlist If the string violates the locale format, or language is not a diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp index 5010af17c8..1571d2dfc9 100644 --- a/src/qml/util/qqmlpropertymap.cpp +++ b/src/qml/util/qqmlpropertymap.cpp @@ -146,7 +146,7 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu key will be updated as well. To detect value changes made in the UI layer you can connect to the valueChanged() signal. - However, note that valueChanged() is \bold NOT emitted when changes are made by calling insert() + However, note that valueChanged() is \b NOT emitted when changes are made by calling insert() or clear() - it is only emitted when a value is updated from QML. \note It is not possible to remove keys from the map; once a key has been added, you can only @@ -302,7 +302,7 @@ QVariant QQmlPropertyMap::operator[](const QString &key) const This signal is emitted whenever one of the values in the map is changed. \a key is the key corresponding to the \a value that was changed. - \note valueChanged() is \bold NOT emitted when changes are made by calling insert() + \note valueChanged() is \b NOT emitted when changes are made by calling insert() or clear() - it is only emitted when a value is updated from QML. */ diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index f89ac186eb..4f849c771b 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -169,13 +169,13 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate() Although the Canvas item is provides a HTML5 like API, HTML5 canvas applications need to be modified to run in the Canvas item: \list - \o Replace all DOM API calls with QML property bindings or Canvas item methods. - \o Replace all HTML event handlers with the \a MouseArea item. - \o Change setInterval/setTimeout function calls with the \a Timer item or + \li Replace all DOM API calls with QML property bindings or Canvas item methods. + \li Replace all HTML event handlers with the \a MouseArea item. + \li Change setInterval/setTimeout function calls with the \a Timer item or the use of requestAnimationFrame. - \o Place painting code into the \a QtQuick2::Canvas::onPaint handler and trigger + \li Place painting code into the \a QtQuick2::Canvas::onPaint handler and trigger painting by calling the \c markDirty or \c requestPaint methods. - \o To draw images, load them by calling the Canvas's loadImage method and then request to paint + \li To draw images, load them by calling the Canvas's loadImage method and then request to paint them in the onImageLoaded handler. \endlist @@ -369,8 +369,8 @@ void QQuickCanvasItem::setCanvasWindow(const QRectF& rect) Holds the current canvas render target. \list - \o Canvas.Image - render to an in memory image buffer. - \o Canvas.FramebufferObject - render to an OpenGL frame buffer + \li Canvas.Image - render to an in memory image buffer. + \li Canvas.FramebufferObject - render to an OpenGL frame buffer \endlist This hint is supplied along with renderStrategy to the graphics context to @@ -404,9 +404,9 @@ void QQuickCanvasItem::setRenderTarget(QQuickCanvasItem::RenderTarget target) Holds the current canvas rendering strategy. \list - \o Canvas.Immediate - context will perform graphics commands immediately in the main UI thread. - \o Canvas.Threaded - context will defer graphics commands to a private rendering thread. - \o Canvas.Cooperative - context will defer graphics commands to the applications global render thread. + \li Canvas.Immediate - context will perform graphics commands immediately in the main UI thread. + \li Canvas.Threaded - context will defer graphics commands to a private rendering thread. + \li Canvas.Cooperative - context will defer graphics commands to the applications global render thread. \endlist This hint is supplied along with renderTarget to the graphics context to diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 05577e8c5c..f8e5e3c57f 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -86,7 +86,7 @@ QT_BEGIN_NAMESPACE {http://www.w3.org/TR/2dcontext}{W3C Canvas 2D Context API standard} with some enhanced features. - The Context2D API provides the rendering \bold{context} which defines the + The Context2D API provides the rendering \b{context} which defines the methods and attributes needed to draw on the \c Canvas item. The following assigns the canvas rendering context to a \c{context} variable: \code @@ -495,22 +495,22 @@ static v8::Handle ctx2d_reset(const v8::Arguments &args) Each state consists of the current transformation matrix, clipping region, and values of the following attributes: \list - \o\a QtQuick2::Context2D::strokeStyle - \o\a QtQuick2::Context2D::fillStyle - \o\a QtQuick2::Context2D::fillRule - \o\a QtQuick2::Context2D::globalAlpha - \o\a QtQuick2::Context2D::lineWidth - \o\a QtQuick2::Context2D::lineCap - \o\a QtQuick2::Context2D::lineJoin - \o\a QtQuick2::Context2D::miterLimit - \o\a QtQuick2::Context2D::shadowOffsetX - \o\a QtQuick2::Context2D::shadowOffsetY - \o\a QtQuick2::Context2D::shadowBlur - \o\a QtQuick2::Context2D::shadowColor - \o\a QtQuick2::Context2D::globalCompositeOperation - \o\a QtQuick2::Context2D::font - \o\a QtQuick2::Context2D::textAlign - \o\a QtQuick2::Context2D::textBaseline + \li\a QtQuick2::Context2D::strokeStyle + \li\a QtQuick2::Context2D::fillStyle + \li\a QtQuick2::Context2D::fillRule + \li\a QtQuick2::Context2D::globalAlpha + \li\a QtQuick2::Context2D::lineWidth + \li\a QtQuick2::Context2D::lineCap + \li\a QtQuick2::Context2D::lineJoin + \li\a QtQuick2::Context2D::miterLimit + \li\a QtQuick2::Context2D::shadowOffsetX + \li\a QtQuick2::Context2D::shadowOffsetY + \li\a QtQuick2::Context2D::shadowBlur + \li\a QtQuick2::Context2D::shadowColor + \li\a QtQuick2::Context2D::globalCompositeOperation + \li\a QtQuick2::Context2D::font + \li\a QtQuick2::Context2D::textAlign + \li\a QtQuick2::Context2D::textBaseline \endlist The current path is NOT part of the drawing state. The path can be reset by @@ -606,19 +606,19 @@ static v8::Handle ctx2d_scale(const v8::Arguments &args) \image qml-item-canvas-math.png where: \list - \o \c{a} is the scale factor in the horizontal (x) direction + \li \c{a} is the scale factor in the horizontal (x) direction \image qml-item-canvas-scalex.png - \o \c{c} is the skew factor in the x direction + \li \c{c} is the skew factor in the x direction \image qml-item-canvas-canvas-skewx.png - \o \c{e} is the translation in the x direction + \li \c{e} is the translation in the x direction \image qml-item-canvas-canvas-translate.png - \o \c{b} is the skew factor in the y (vertical) direction + \li \c{b} is the skew factor in the y (vertical) direction \image qml-item-canvas-canvas-skewy.png - \o \c{d} is the scale factor in the y direction + \li \c{d} is the scale factor in the y direction \image qml-item-canvas-canvas-scaley.png - \o \c{f} is the translation in the y direction + \li \c{f} is the translation in the y direction \image qml-item-canvas-canvas-translatey.png - \o the last row remains constant + \li the last row remains constant \endlist The scale factors and skew factors are multiples; \c{e} and \c{f} are coordinate space units, just like the units in the \a QtQuick2::Context2D::translate(x,y) @@ -799,22 +799,22 @@ static void ctx2d_globalAlpha_set(v8::Local, v8::Local va \qmlproperty string QtQuick2::Context2D::globalCompositeOperation Holds the the current the current composition operation, from the list below: \list - \o source-atop - A atop B. Display the source image wherever both images are opaque. + \li source-atop - A atop B. Display the source image wherever both images are opaque. Display the destination image wherever the destination image is opaque but the source image is transparent. Display transparency elsewhere. - \o source-in - A in B. Display the source image wherever both the source image and destination image are opaque. + \li source-in - A in B. Display the source image wherever both the source image and destination image are opaque. Display transparency elsewhere. - \o source-out - A out B. Display the source image wherever the source image is opaque and the destination image is transparent. + \li source-out - A out B. Display the source image wherever the source image is opaque and the destination image is transparent. Display transparency elsewhere. - \o source-over - (default) A over B. Display the source image wherever the source image is opaque. + \li source-over - (default) A over B. Display the source image wherever the source image is opaque. Display the destination image elsewhere. - \o destination-atop - B atop A. Same as source-atop but using the destination image instead of the source image and vice versa. - \o destination-in - B in A. Same as source-in but using the destination image instead of the source image and vice versa. - \o destination-out - B out A. Same as source-out but using the destination image instead of the source image and vice versa. - \o destination-over - B over A. Same as source-over but using the destination image instead of the source image and vice versa. - \o lighter - A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit. - \o copy - A (B is ignored). Display the source image instead of the destination image. - \o xor - A xor B. Exclusive OR of the source image and destination image. + \li destination-atop - B atop A. Same as source-atop but using the destination image instead of the source image and vice versa. + \li destination-in - B in A. Same as source-in but using the destination image instead of the source image and vice versa. + \li destination-out - B out A. Same as source-out but using the destination image instead of the source image and vice versa. + \li destination-over - B over A. Same as source-over but using the destination image instead of the source image and vice versa. + \li lighter - A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit. + \li copy - A (B is ignored). Display the source image instead of the destination image. + \li xor - A xor B. Exclusive OR of the source image and destination image. \endlist Additionally, this property also accepts the compositon modes listed in \a {QPainter::CompositionMode}. According to the W3C standard, these @@ -858,12 +858,12 @@ static void ctx2d_globalCompositeOperation_set(v8::Local, v8::Local< The style can be either a string containing a CSS color, a CanvasGradient or CanvasPattern object. Invalid values are ignored. This property accepts several color syntaxes: \list - \o 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)' - \o 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)' - \o 'hsl(hue, saturation, lightness)' - \o 'hsla(hue, saturation, lightness, alpha)' - \o '#RRGGBB' - for example: '#00FFCC' - \o Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0) + \li 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)' + \li 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)' + \li 'hsl(hue, saturation, lightness)' + \li 'hsla(hue, saturation, lightness, alpha)' + \li '#RRGGBB' - for example: '#00FFCC' + \li Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0) \endlist If the \a fillStyle or \a strokeStyle is assigned many times in a loop, the last Qt.rgba() syntax should be chosen, as it has the best performance, because it's already a valid QColor value, does not need to be parsed everytime. @@ -931,8 +931,8 @@ static void ctx2d_fillStyle_set(v8::Local, v8::Local valu \qmlproperty enumeration QtQuick2::Context2D::fillRule Holds the current fill rule used for filling shapes. The following fill rules supported: \list - \o Qt.OddEvenFill - \o Qt.WindingFill + \li Qt.OddEvenFill + \li Qt.WindingFill \endlist Note: Unlike the \a QPainterPath, the Canvas API uses the winding fill as the default fill rule. The fillRule property is part of the context rendering state. @@ -1183,20 +1183,20 @@ static v8::Handle ctx2d_createConicalGradient(const v8::Arguments &ar Returns a CanvasPattern object that uses the given \c color and \c patternMode. The valid pattern modes are: \list - \o Qt.SolidPattern - \o Qt.Dense1Pattern - \o Qt.Dense2Pattern - \o Qt.Dense3Pattern - \o Qt.Dense4Pattern - \o Qt.Dense5Pattern - \o Qt.Dense6Pattern - \o Qt.Dense7Pattern - \o Qt.HorPattern - \o Qt.VerPattern - \o Qt.CrossPattern - \o Qt.BDiagPattern - \o Qt.FDiagPattern - \o Qt.DiagCrossPattern + \li Qt.SolidPattern + \li Qt.Dense1Pattern + \li Qt.Dense2Pattern + \li Qt.Dense3Pattern + \li Qt.Dense4Pattern + \li Qt.Dense5Pattern + \li Qt.Dense6Pattern + \li Qt.Dense7Pattern + \li Qt.HorPattern + \li Qt.VerPattern + \li Qt.CrossPattern + \li Qt.BDiagPattern + \li Qt.FDiagPattern + \li Qt.DiagCrossPattern \endlist \sa Qt::BrushStyle */ @@ -1209,10 +1209,10 @@ static v8::Handle ctx2d_createConicalGradient(const v8::Arguments &ar The allowed values for \a repetition are: \list - \o "repeat" - both directions - \o "repeat-x - horizontal only - \o "repeat-y" - vertical only - \o "no-repeat" - neither + \li "repeat" - both directions + \li "repeat-x - horizontal only + \li "repeat-y" - vertical only + \li "no-repeat" - neither \endlist If the repetition argument is empty or null, the value "repeat" is used. @@ -1287,9 +1287,9 @@ static v8::Handle ctx2d_createPattern(const v8::Arguments &args) Holds the the current line cap style. The possible line cap styles are: \list - \o butt - the end of each line has a flat edge perpendicular to the direction of the line, this is the default line cap value. - \o round - a semi-circle with the diameter equal to the width of the line must then be added on to the end of the line. - \o square - a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line. + \li butt - the end of each line has a flat edge perpendicular to the direction of the line, this is the default line cap value. + \li round - a semi-circle with the diameter equal to the width of the line must then be added on to the end of the line. + \li square - a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line. \endlist Other values are ignored. */ @@ -1345,9 +1345,9 @@ static void ctx2d_lineCap_set(v8::Local, v8::Local value, The possible line join styles are: \list - \o bevel - this is all that is rendered at joins. - \o round - a filled arc connecting the two aforementioned corners of the join, abutting (and not overlapping) the aforementioned triangle, with the diameter equal to the line width and the origin at the point of the join, must be rendered at joins. - \o miter - a second filled triangle must (if it can given the miter length) be rendered at the join, this is the default line join style. + \li bevel - this is all that is rendered at joins. + \li round - a filled arc connecting the two aforementioned corners of the join, abutting (and not overlapping) the aforementioned triangle, with the diameter equal to the line width and the origin at the point of the join, must be rendered at joins. + \li miter - a second filled triangle must (if it can given the miter length) be rendered at the join, this is the default line join style. \endlist Other values are ignored. */ @@ -1711,9 +1711,9 @@ static v8::Handle ctx2d_arc(const v8::Arguments &args) Adds an arc with the given control points and radius to the current subpath, connected to the previous point by a straight line. To draw an arc, you begin with the same steps your followed to create a line: \list - \o Call the context.beginPath() method to set a new path. - \o Call the context.moveTo(\c x, \c y) method to set your starting position on the canvas at the point (\c x,\c y). - \o To draw an arc or circle, call the context.arcTo(\c x1, \c y1, \c x2, \c y2,\c radius) method. + \li Call the context.beginPath() method to set a new path. + \li Call the context.moveTo(\c x, \c y) method to set your starting position on the canvas at the point (\c x,\c y). + \li To draw an arc or circle, call the context.arcTo(\c x1, \c y1, \c x2, \c y2,\c radius) method. This adds an arc with starting point (\c x1,\c y1), ending point (\c x2, \c y2), and radius \c radius to the current subpath and connects it to the previous subpath by a straight line. \endlist @@ -1820,10 +1820,10 @@ static v8::Handle ctx2d_bezierCurveTo(const v8::Arguments &args) To create a complex shape using the \a clip() method: \list 1 - \o Call the \c{context.beginPath()} method to set the clipping path. - \o Define the clipping path by calling any combination of the \c{lineTo}, + \li Call the \c{context.beginPath()} method to set the clipping path. + \li Define the clipping path by calling any combination of the \c{lineTo}, \c{arcTo}, \c{arc}, \c{moveTo}, etc and \c{closePath} methods. - \o Call the \c{context.clip()} method. + \li Call the \c{context.clip()} method. \endlist The new shape displays. The following shows how a clipping path can @@ -2168,11 +2168,11 @@ static void ctx2d_font_set(v8::Local, v8::Local value, co Holds the current text alignment settings. The possible values are: \list - \o start - \o end - \o left - \o right - \o center + \li start + \li end + \li left + \li right + \li center \endlist Other values are ignored. The default value is "start". */ @@ -2231,12 +2231,12 @@ static void ctx2d_textAlign_set(v8::Local, v8::Local valu Holds the current baseline alignment settings. The possible values are: \list - \o top - \o hanging - \o middle - \o alphabetic - \o ideographic - \o bottom + \li top + \li hanging + \li middle + \li alphabetic + \li ideographic + \li bottom \endlist Other values are ignored. The default value is "alphabetic". */ diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 20082e8002..fcf62fa910 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -113,22 +113,22 @@ QT_BEGIN_NAMESPACE \table \header - \o \bold {Role} - \o \bold {Expected property} - \o + \li \b {Role} + \li \b {Expected property} + \li \row - \o Button - \o function accessiblePressAction - \o Called when the button receives a press action. The implementation should visually simulate a button click and perform the button action. + \li Button + \li function accessiblePressAction + \li Called when the button receives a press action. The implementation should visually simulate a button click and perform the button action. \row - \o CheckBox, Radiobutton - \o checked - \o The check state of the check box. Updated on Press, Check and Uncheck actions. + \li CheckBox, Radiobutton + \li checked + \li The check state of the check box. Updated on Press, Check and Uncheck actions. \row - \o Slider, SpinBox, Dial, ScrollBar - \o value, minimumValue, maximumValue, stepSize - \o value will be updated on increase and decrase actions, in accordance with the other properties + \li Slider, SpinBox, Dial, ScrollBar + \li value, minimumValue, maximumValue, stepSize + \li value will be updated on increase and decrase actions, in accordance with the other properties \endtable */ diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index eef20db361..6567892fb4 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE about its state, such as the current frame and total number of frames. The result is an animated image with a simple progress indicator underneath it. - \bold Note: Unlike images, animated images are not cached or shared internally. + \b Note: Unlike images, animated images are not cached or shared internally. \clearfloat \snippet doc/src/snippets/qml/animatedimage.qml document diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 5beb345afc..71514593a3 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -71,12 +71,12 @@ QT_BEGIN_NAMESPACE create the displayed border image in the following way: \list - \i The corners (regions 1, 3, 7, and 9) are not scaled at all. - \i Regions 2 and 8 are scaled according to + \li The corners (regions 1, 3, 7, and 9) are not scaled at all. + \li Regions 2 and 8 are scaled according to \l{BorderImage::horizontalTileMode}{horizontalTileMode}. - \i Regions 4 and 6 are scaled according to + \li Regions 4 and 6 are scaled according to \l{BorderImage::verticalTileMode}{verticalTileMode}. - \i The middle (region 5) is scaled according to both + \li The middle (region 5) is scaled according to both \l{BorderImage::horizontalTileMode}{horizontalTileMode} and \l{BorderImage::verticalTileMode}{verticalTileMode}. \endlist @@ -182,10 +182,10 @@ QQuickBorderImage::~QQuickBorderImage() This property describes the status of image loading. It can be one of: \list - \o BorderImage.Null - no image has been set - \o BorderImage.Ready - the image has been loaded - \o BorderImage.Loading - the image is currently being loaded - \o BorderImage.Error - an error occurred while loading the image + \li BorderImage.Null - no image has been set + \li BorderImage.Ready - the image has been loaded + \li BorderImage.Loading - the image is currently being loaded + \li BorderImage.Error - an error occurred while loading the image \endlist \sa progress @@ -393,9 +393,9 @@ QQuickScaleGrid *QQuickBorderImage::border() This property describes how to repeat or stretch the middle parts of the border image. \list - \o BorderImage.Stretch - Scales the image to fit to the available area. - \o BorderImage.Repeat - Tile the image until there is no more space. May crop the last image. - \o BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped. + \li BorderImage.Stretch - Scales the image to fit to the available area. + \li BorderImage.Repeat - Tile the image until there is no more space. May crop the last image. + \li BorderImage.Round - Like Repeat, but scales the images down to ensure that the last image is not cropped. \endlist The default tile mode for each property is BorderImage.Stretch. diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index f8c1281af5..3316169741 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -410,10 +410,10 @@ void QQuickDragAttached::start(QQmlV8Function *args) The returned drop action may be one of: \list - \o Qt.CopyAction Copy the data to the target - \o Qt.MoveAction Move the data from the source to the target - \o Qt.LinkAction Create a link from the source to the target. - \o Qt.IgnoreAction Ignore the action (do nothing with the data). + \li Qt.CopyAction Copy the data to the target + \li Qt.MoveAction Move the data from the source to the target + \li Qt.LinkAction Create a link from the source to the target. + \li Qt.IgnoreAction Ignore the action (do nothing with the data). \endlist */ diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp index ed5fb23658..51ba4c56ec 100644 --- a/src/quick/items/qquickdroparea.cpp +++ b/src/quick/items/qquickdroparea.cpp @@ -378,10 +378,10 @@ QStringList QQuickDropEvent::keys() const The drop action may be one of: \list - \o Qt.CopyAction Copy the data to the target - \o Qt.MoveAction Move the data from the source to the target - \o Qt.LinkAction Create a link from the source to the target. - \o Qt.IgnoreAction Ignore the action (do nothing with the data). + \li Qt.CopyAction Copy the data to the target + \li Qt.MoveAction Move the data from the source to the target + \li Qt.LinkAction Create a link from the source to the target. + \li Qt.IgnoreAction Ignore the action (do nothing with the data). \endlist */ diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 9222a7766d..bf58e4411d 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -117,12 +117,12 @@ Item { It contains a bitwise combination of: \list - \o Qt.NoModifier - No modifier key is pressed. - \o Qt.ShiftModifier - A Shift key on the keyboard is pressed. - \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed. - \o Qt.AltModifier - An Alt key on the keyboard is pressed. - \o Qt.MetaModifier - A Meta key on the keyboard is pressed. - \o Qt.KeypadModifier - A keypad button is pressed. + \li Qt.NoModifier - No modifier key is pressed. + \li Qt.ShiftModifier - A Shift key on the keyboard is pressed. + \li Qt.ControlModifier - A Ctrl key on the keyboard is pressed. + \li Qt.AltModifier - An Alt key on the keyboard is pressed. + \li Qt.MetaModifier - A Meta key on the keyboard is pressed. + \li Qt.KeypadModifier - A keypad button is pressed. \endlist For example, to react to a Shift key + Enter key combination: @@ -179,9 +179,9 @@ Item { This property holds the button that caused the event. It can be one of: \list - \o Qt.LeftButton - \o Qt.RightButton - \o Qt.MiddleButton + \li Qt.LeftButton + \li Qt.RightButton + \li Qt.MiddleButton \endlist */ @@ -202,9 +202,9 @@ Item { It contains a bitwise combination of: \list - \o Qt.LeftButton - \o Qt.RightButton - \o Qt.MiddleButton + \li Qt.LeftButton + \li Qt.RightButton + \li Qt.MiddleButton \endlist */ @@ -216,12 +216,12 @@ Item { It contains a bitwise combination of: \list - \o Qt.NoModifier - No modifier key is pressed. - \o Qt.ShiftModifier - A Shift key on the keyboard is pressed. - \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed. - \o Qt.AltModifier - An Alt key on the keyboard is pressed. - \o Qt.MetaModifier - A Meta key on the keyboard is pressed. - \o Qt.KeypadModifier - A keypad button is pressed. + \li Qt.NoModifier - No modifier key is pressed. + \li Qt.ShiftModifier - A Shift key on the keyboard is pressed. + \li Qt.ControlModifier - A Ctrl key on the keyboard is pressed. + \li Qt.AltModifier - An Alt key on the keyboard is pressed. + \li Qt.MetaModifier - A Meta key on the keyboard is pressed. + \li Qt.KeypadModifier - A keypad button is pressed. \endlist For example, to react to a Shift key + Left mouse button click: @@ -277,9 +277,9 @@ Item { It contains a bitwise combination of: \list - \o Qt.LeftButton - \o Qt.RightButton - \o Qt.MiddleButton + \li Qt.LeftButton + \li Qt.RightButton + \li Qt.MiddleButton \endlist */ @@ -317,12 +317,12 @@ Item { It contains a bitwise combination of: \list - \o Qt.NoModifier - No modifier key is pressed. - \o Qt.ShiftModifier - A Shift key on the keyboard is pressed. - \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed. - \o Qt.AltModifier - An Alt key on the keyboard is pressed. - \o Qt.MetaModifier - A Meta key on the keyboard is pressed. - \o Qt.KeypadModifier - A keypad button is pressed. + \li Qt.NoModifier - No modifier key is pressed. + \li Qt.ShiftModifier - A Shift key on the keyboard is pressed. + \li Qt.ControlModifier - A Ctrl key on the keyboard is pressed. + \li Qt.AltModifier - An Alt key on the keyboard is pressed. + \li Qt.MetaModifier - A Meta key on the keyboard is pressed. + \li Qt.KeypadModifier - A keypad button is pressed. \endlist For example, to react to a Control key pressed during the wheel event: diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 82f674741f..2447fd6ed1 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -771,13 +771,13 @@ QQuickFlickableVisibleArea *QQuickFlickable::visibleArea() This property determines which directions the view can be flicked. \list - \o Flickable.AutoFlickDirection (default) - allows flicking vertically if the + \li Flickable.AutoFlickDirection (default) - allows flicking vertically if the \e contentHeight is not equal to the \e height of the Flickable. Allows flicking horizontally if the \e contentWidth is not equal to the \e width of the Flickable. - \o Flickable.HorizontalFlick - allows flicking horizontally. - \o Flickable.VerticalFlick - allows flicking vertically. - \o Flickable.HorizontalAndVerticalFlick - allows flicking in both directions. + \li Flickable.HorizontalFlick - allows flicking horizontally. + \li Flickable.VerticalFlick - allows flicking vertically. + \li Flickable.HorizontalAndVerticalFlick - allows flicking in both directions. \endlist */ QQuickFlickable::FlickableDirection QQuickFlickable::flickableDirection() const @@ -1449,11 +1449,11 @@ QQmlListProperty QQuickFlickable::flickableChildren() The \c boundsBehavior can be one of: \list - \o Flickable.StopAtBounds - the contents can not be dragged beyond the boundary + \li Flickable.StopAtBounds - the contents can not be dragged beyond the boundary of the flickable, and flicks will not overshoot. - \o Flickable.DragOverBounds - the contents can be dragged beyond the boundary + \li Flickable.DragOverBounds - the contents can be dragged beyond the boundary of the Flickable, but flicks will not overshoot. - \o Flickable.DragAndOvershootBounds (default) - the contents can be dragged + \li Flickable.DragAndOvershootBounds (default) - the contents can be dragged beyond the boundary of the Flickable, and can overshoot the boundary when flicked. \endlist diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 78899b27e5..dd7a3faa6f 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -1344,13 +1344,13 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) Valid values for \c highlightRangeMode are: \list - \o GridView.ApplyRange - the view attempts to maintain the highlight within the range. + \li GridView.ApplyRange - the view attempts to maintain the highlight within the range. However, the highlight can move outside of the range at the ends of the view or due to mouse interaction. - \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range. + \li GridView.StrictlyEnforceRange - the highlight never moves outside of the range. The current item changes if a keyboard or mouse action would cause the highlight to move outside of the range. - \o GridView.NoHighlightRange - this is the default value. + \li GridView.NoHighlightRange - this is the default value. \endlist */ @@ -1362,13 +1362,13 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) Possible values: \list - \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is + \li Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is dependent on the \l GridView::flow property. - \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent + \li Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent on the \l GridView::flow property. \endlist - \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if + \b Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply indicates that the flow is horizontal. */ @@ -1437,8 +1437,8 @@ void QQuickGridView::setHighlightMoveDuration(int duration) Possible values: \list - \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically - \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally + \li GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically + \li GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally \endlist */ QQuickGridView::Flow QQuickGridView::flow() const @@ -1517,10 +1517,10 @@ void QQuickGridView::setCellHeight(qreal cellHeight) The possible values are: \list - \o GridView.NoSnap (default) - the view stops anywhere within the visible area. - \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow) + \li GridView.NoSnap (default) - the view stops anywhere within the visible area. + \li GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow) aligned with the start of the view. - \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow) + \li GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow) away from the first visible row at the time the mouse button is released. This mode is particularly useful for moving one page at a time. \endlist @@ -1590,9 +1590,9 @@ void QQuickGridView::setSnapMode(SnapMode mode) It is applied to all items that are created when: \list - \o The view is first created - \o The view's \l model changes - \o The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass + \li The view is first created + \li The view's \l model changes + \li The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass \endlist For example, here is a view that specifies such a transition: @@ -1971,7 +1971,7 @@ void QQuickGridView::geometryChanged(const QRectF &newGeometry, const QRectF &ol The current index will wrap if keyNavigationWraps is true and it is currently at the end. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ @@ -2001,7 +2001,7 @@ void QQuickGridView::moveCurrentIndexUp() The current index will wrap if keyNavigationWraps is true and it is currently at the end. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickGridView::moveCurrentIndexDown() { @@ -2029,7 +2029,7 @@ void QQuickGridView::moveCurrentIndexDown() The current index will wrap if keyNavigationWraps is true and it is currently at the end. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickGridView::moveCurrentIndexLeft() { @@ -2072,7 +2072,7 @@ void QQuickGridView::moveCurrentIndexLeft() The current index will wrap if keyNavigationWraps is true and it is currently at the end. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickGridView::moveCurrentIndexRight() { @@ -2307,12 +2307,12 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co \a mode: \list - \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view. - \o GridView.Center - position item in the center of the view. - \o GridView.End - position item at bottom (or right for horizontal orientation) of the view. - \o GridView.Visible - if any part of the item is visible then take no action, otherwise + \li GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view. + \li GridView.Center - position item in the center of the view. + \li GridView.End - position item at bottom (or right for horizontal orientation) of the view. + \li GridView.Visible - if any part of the item is visible then take no action, otherwise bring the item into view. - \o GridView.Contain - ensure the entire item is visible. If the item is larger than + \li GridView.Contain - ensure the entire item is visible. If the item is larger than the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view. \endlist @@ -2324,7 +2324,7 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co of the view does not cause all other items to be repositioned. The correct way to bring an item into view is with \c positionViewAtIndex. - \bold Note: methods should only be called after the Component has completed. To position + \b Note: methods should only be called after the Component has completed. To position the view at startup, this method should be called by Component.onCompleted. For example, to position the view at the end: @@ -2344,7 +2344,7 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co of the list does not cause all other items to be repositioned, and because the actual start of the view can vary based on the size of the delegates. - \bold Note: methods should only be called after the Component has completed. To position + \b Note: methods should only be called after the Component has completed. To position the view at startup, this method should be called by Component.onCompleted. For example, to position the view at the end on startup: @@ -2363,7 +2363,7 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co If the item is outside the visible area, -1 is returned, regardless of whether an item will exist at that point when scrolled into view. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ /*! @@ -2376,7 +2376,7 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co If the item is outside the visible area, null is returned, regardless of whether an item will exist at that point when scrolled into view. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ QQuickGridViewAttached *QQuickGridView::qmlAttachedProperties(QObject *obj) diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index a939365e98..2346689178 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -142,7 +142,7 @@ QQuickImagePrivate::QQuickImagePrivate() Images are cached and shared internally, so if several Image elements have the same \l source, only one copy of the image will be loaded. - \bold Note: Images are often the greatest user of memory in QML user interfaces. It is recommended + \b Note: Images are often the greatest user of memory in QML user interfaces. It is recommended that images which do not form part of the user interface have their size bounded via the \l sourceSize property. This is especially important for content that is loaded from external sources or provided by the user. @@ -185,20 +185,20 @@ void QQuickImagePrivate::setImage(const QImage &image) than the item. \list - \o Image.Stretch - the image is scaled to fit - \o Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping - \o Image.PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary - \o Image.Tile - the image is duplicated horizontally and vertically - \o Image.TileVertically - the image is stretched horizontally and tiled vertically - \o Image.TileHorizontally - the image is stretched vertically and tiled horizontally - \o Image.Pad - the image is not transformed + \li Image.Stretch - the image is scaled to fit + \li Image.PreserveAspectFit - the image is scaled uniformly to fit without cropping + \li Image.PreserveAspectCrop - the image is scaled uniformly to fill, cropping if necessary + \li Image.Tile - the image is duplicated horizontally and vertically + \li Image.TileVertically - the image is stretched horizontally and tiled vertically + \li Image.TileHorizontally - the image is stretched vertically and tiled horizontally + \li Image.Pad - the image is not transformed \endlist \table \row - \o \image declarative-qtlogo-stretch.png - \o Stretch (default) + \li \image declarative-qtlogo-stretch.png + \li Stretch (default) \qml Image { width: 130; height: 100 @@ -208,8 +208,8 @@ void QQuickImagePrivate::setImage(const QImage &image) \endqml \row - \o \image declarative-qtlogo-preserveaspectfit.png - \o PreserveAspectFit + \li \image declarative-qtlogo-preserveaspectfit.png + \li PreserveAspectFit \qml Image { width: 130; height: 100 @@ -220,8 +220,8 @@ void QQuickImagePrivate::setImage(const QImage &image) \endqml \row - \o \image declarative-qtlogo-preserveaspectcrop.png - \o PreserveAspectCrop + \li \image declarative-qtlogo-preserveaspectcrop.png + \li PreserveAspectCrop \qml Image { width: 130; height: 100 @@ -233,8 +233,8 @@ void QQuickImagePrivate::setImage(const QImage &image) \endqml \row - \o \image declarative-qtlogo-tile.png - \o Tile + \li \image declarative-qtlogo-tile.png + \li Tile \qml Image { width: 120; height: 120 @@ -244,8 +244,8 @@ void QQuickImagePrivate::setImage(const QImage &image) \endqml \row - \o \image declarative-qtlogo-tilevertically.png - \o TileVertically + \li \image declarative-qtlogo-tilevertically.png + \li TileVertically \qml Image { width: 120; height: 120 @@ -256,8 +256,8 @@ void QQuickImagePrivate::setImage(const QImage &image) \endqml \row - \o \image declarative-qtlogo-tilehorizontally.png - \o TileHorizontally + \li \image declarative-qtlogo-tilehorizontally.png + \li TileHorizontally \qml Image { width: 120; height: 120 @@ -319,22 +319,22 @@ qreal QQuickImage::paintedHeight() const This property holds the status of image loading. It can be one of: \list - \o Image.Null - no image has been set - \o Image.Ready - the image has been loaded - \o Image.Loading - the image is currently being loaded - \o Image.Error - an error occurred while loading the image + \li Image.Null - no image has been set + \li Image.Ready - the image has been loaded + \li Image.Loading - the image is currently being loaded + \li Image.Error - an error occurred while loading the image \endlist Use this status to provide an update or respond to the status change in some way. For example, you could: \list - \o Trigger a state change: + \li Trigger a state change: \qml State { name: 'loaded'; when: image.status == Image.Ready } \endqml - \o Implement an \c onStatusChanged signal handler: + \li Implement an \c onStatusChanged signal handler: \qml Image { id: image @@ -342,7 +342,7 @@ qreal QQuickImage::paintedHeight() const } \endqml - \o Bind to the status value: + \li Bind to the status value: \qml Text { text: image.status == Image.Ready ? 'Loaded' : 'Not loaded' } \endqml diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 8f9a060329..e605f2ea7e 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -116,9 +116,9 @@ void QQuickItemPrivate::registerAccessorProperties() The following concrete Transform types are available: \list - \o \l Rotation - \o \l Scale - \o \l Translate + \li \l Rotation + \li \l Scale + \li \l Translate \endlist The Transform elements let you create and control advanced transformations that can be configured @@ -696,10 +696,10 @@ void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i) or after the attached item's own key handling. \list - \o KeyNavigation.BeforeItem - process the key events before normal + \li KeyNavigation.BeforeItem - process the key events before normal item key processing. If the event is used for key navigation, it will be accepted and will not be passed on to the item. - \o KeyNavigation.AfterItem (default) - process the key events after normal item key + \li KeyNavigation.AfterItem (default) - process the key events after normal item key handling. If the item accepts the key event it will not be handled by the KeyNavigation attached property handler. \endlist @@ -933,21 +933,21 @@ bool QQuickKeysAttachedPrivate::isConnected(const char *signalName) If \l priority is Keys.BeforeItem (default) the order of key event processing is: \list 1 - \o Items specified in \c forwardTo - \o specific key handlers, e.g. onReturnPressed - \o onKeyPress, onKeyRelease handlers - \o Item specific key handling, e.g. TextInput key handling - \o parent item + \li Items specified in \c forwardTo + \li specific key handlers, e.g. onReturnPressed + \li onKeyPress, onKeyRelease handlers + \li Item specific key handling, e.g. TextInput key handling + \li parent item \endlist If priority is Keys.AfterItem the order of key event processing is: \list 1 - \o Item specific key handling, e.g. TextInput key handling - \o Items specified in \c forwardTo - \o specific key handlers, e.g. onReturnPressed - \o onKeyPress, onKeyRelease handlers - \o parent item + \li Item specific key handling, e.g. TextInput key handling + \li Items specified in \c forwardTo + \li specific key handlers, e.g. onReturnPressed + \li onKeyPress, onKeyRelease handlers + \li parent item \endlist If the event is accepted during any of the above steps, key @@ -970,10 +970,10 @@ bool QQuickKeysAttachedPrivate::isConnected(const char *signalName) or after the attached item's own key handling. \list - \o Keys.BeforeItem (default) - process the key events before normal + \li Keys.BeforeItem (default) - process the key events before normal item key processing. If the event is accepted it will not be passed on to the item. - \o Keys.AfterItem - process the key events after normal item key + \li Keys.AfterItem - process the key events after normal item key handling. If the item accepts the key event it will not be handled by the Keys attached property handler. \endlist @@ -2644,8 +2644,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) \table \row - \o \image declarative-item_stacking1.png - \o Same \c z - later children above earlier children: + \li \image declarative-item_stacking1.png + \li Same \c z - later children above earlier children: \qml Item { Rectangle { @@ -2659,8 +2659,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) } \endqml \row - \o \image declarative-item_stacking2.png - \o Higher \c z on top: + \li \image declarative-item_stacking2.png + \li Higher \c z on top: \qml Item { Rectangle { @@ -2675,8 +2675,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) } \endqml \row - \o \image declarative-item_stacking3.png - \o Same \c z - children above parents: + \li \image declarative-item_stacking3.png + \li Same \c z - children above parents: \qml Item { Rectangle { @@ -2690,8 +2690,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) } \endqml \row - \o \image declarative-item_stacking4.png - \o Lower \c z below: + \li \image declarative-item_stacking4.png + \li Lower \c z below: \qml Item { Rectangle { @@ -2769,8 +2769,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) \table \row - \o \image declarative-anchors_example.png - \o Text anchored to Image, horizontally centered and vertically below, with a margin. + \li \image declarative-anchors_example.png + \li Text anchored to Image, horizontally centered and vertically below, with a margin. \qml Item { Image { @@ -2787,8 +2787,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) } \endqml \row - \o \image declarative-anchors_example2.png - \o + \li \image declarative-anchors_example2.png + \li Left of Text anchored to right of Image, with a margin. The y property of both defaults to 0. @@ -3727,8 +3727,8 @@ void QQuickItem::setZ(qreal v) \table \row - \o \image declarative-rotation.png - \o + \li \image declarative-rotation.png + \li \qml Rectangle { color: "blue" @@ -3761,8 +3761,8 @@ void QQuickItem::setZ(qreal v) \table \row - \o \image declarative-scale.png - \o + \li \image declarative-scale.png + \li \qml Rectangle { color: "blue" @@ -3798,8 +3798,8 @@ void QQuickItem::setZ(qreal v) \table \row - \o \image declarative-item_opacity1.png - \o + \li \image declarative-item_opacity1.png + \li \qml Item { Rectangle { @@ -3813,8 +3813,8 @@ void QQuickItem::setZ(qreal v) } \endqml \row - \o \image declarative-item_opacity2.png - \o + \li \image declarative-item_opacity2.png + \li \qml Item { Rectangle { @@ -4438,7 +4438,7 @@ qreal QQuickItem::implicitWidth() const } \endqml - \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly + \b Note: using implicitWidth of Text or TextEdit and setting the width explicitly incurs a performance penalty as the text must be laid out twice. */ @@ -5631,9 +5631,9 @@ void QQuickItemLayer::setMipmap(bool mipmap) allow you to save some texture memory. \list - \o ShaderEffectSource.Alpha - GL_ALPHA - \o ShaderEffectSource.RGB - GL_RGB - \o ShaderEffectSource.RGBA - GL_RGBA + \li ShaderEffectSource.Alpha - GL_ALPHA + \li ShaderEffectSource.RGB - GL_RGB + \li ShaderEffectSource.RGBA - GL_RGBA \endlist \note Some OpenGL implementations do not support the GL_ALPHA format. @@ -5728,10 +5728,10 @@ void QQuickItemLayer::setSize(const QSize &size) specified. \list - \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically - \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically - \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically - \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically + \li ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically + \li ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically + \li ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically + \li ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically \endlist \note Some OpenGL ES 2 implementations do not support the GL_REPEAT diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index 32f1047e51..a1c398eeb6 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -701,12 +701,12 @@ void QQuickPathAnimation::setTargetObject(QQuickItem *target) item to achieve the specified orientation as it travels along the path. \list - \o PathAnimation.Fixed (default) - the PathAnimation will not control + \li PathAnimation.Fixed (default) - the PathAnimation will not control the rotation of the item. - \o PathAnimation.RightFirst - The right side of the item will lead along the path. - \o PathAnimation.LeftFirst - The left side of the item will lead along the path. - \o PathAnimation.BottomFirst - The bottom of the item will lead along the path. - \o PathAnimation.TopFirst - The top of the item will lead along the path. + \li PathAnimation.RightFirst - The right side of the item will lead along the path. + \li PathAnimation.LeftFirst - The left side of the item will lead along the path. + \li PathAnimation.BottomFirst - The bottom of the item will lead along the path. + \li PathAnimation.TopFirst - The top of the item will lead along the path. \endlist */ QQuickPathAnimation::Orientation QQuickPathAnimation::orientation() const diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp index 823269bfc1..cdc1c19518 100644 --- a/src/quick/items/qquickitemviewtransition.cpp +++ b/src/quick/items/qquickitemviewtransition.cpp @@ -579,14 +579,14 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) operations: \list - \o \c populate - the transition to run when a view is created, or when the model changes - \o \c add - the transition to apply to items that are added to the view - \o \c remove - the transition to apply to items that are removed from the view - \o \c move - the transition to apply to items that are moved within the view (i.e. as a result + \li \c populate - the transition to run when a view is created, or when the model changes + \li \c add - the transition to apply to items that are added to the view + \li \c remove - the transition to apply to items that are removed from the view + \li \c move - the transition to apply to items that are moved within the view (i.e. as a result of a move operation in the model) - \o \c displaced - the generic transition to be applied to any items that are displaced by an + \li \c displaced - the generic transition to be applied to any items that are displaced by an add, move or remove operation - \o \c addDisplaced, \c removeDisplaced and \c moveDisplaced - the transitions to be applied when + \li \c addDisplaced, \c removeDisplaced and \c moveDisplaced - the transitions to be applied when items are displaced by add, move, or remove operations, respectively (these override the generic displaced transition if specified) \endlist @@ -595,9 +595,9 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) items rather than data models, the following properties are used instead: \list - \o \c add - the transition to apply to items that are created for the positioner, added to + \li \c add - the transition to apply to items that are created for the positioner, added to or reparented to the positioner, or items that have become \l {Item::}{visible} - \o \c move - the transition to apply to items that have moved within the positioner, including + \li \c move - the transition to apply to items that have moved within the positioner, including when they are displaced due to the addition or removal of other items, or when items are otherwise rearranged within the positioner, or when items are repositioned due to the resizing of other items in the positioner @@ -612,17 +612,17 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) which the transition is applied: \list - \o ViewTransition.item - the item that is under transition - \o ViewTransition.index - the index of this item - \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation + \li ViewTransition.item - the item that is under transition + \li ViewTransition.index - the index of this item + \li ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation \endlist In addition, ViewTransition provides properties specific to the items which are the target of the operation that triggered the transition: \list - \o ViewTransition.targetIndexes - the indexes of the target items - \o ViewTransition.targetItems - the target items themselves + \li ViewTransition.targetIndexes - the indexes of the target items + \li ViewTransition.targetItems - the target items themselves \endlist (Note that for the \l Row, \l Column, \l Grid and \l Flow positioner elements, the \c move transition only @@ -679,29 +679,29 @@ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent) \table \header - \o Property - \o Value - \o Explanation + \li Property + \li Value + \li Explanation \row - \o ViewTransition.item - \o "Item 0" delegate instance - \o The "Item 0" \l Rectangle object itself + \li ViewTransition.item + \li "Item 0" delegate instance + \li The "Item 0" \l Rectangle object itself \row - \o ViewTransition.index - \o \c int value of 4 - \o The index of "Item 0" within the model following the add operation + \li ViewTransition.index + \li \c int value of 4 + \li The index of "Item 0" within the model following the add operation \row - \o ViewTransition.destination - \o \l point value of (0, 120) - \o The position that "Item 0" is moving to + \li ViewTransition.destination + \li \l point value of (0, 120) + \li The position that "Item 0" is moving to \row - \o ViewTransition.targetIndexes - \o \c int array, just contains the integer "0" (zero) - \o The index of "Item 4", the new item added to the view + \li ViewTransition.targetIndexes + \li \c int array, just contains the integer "0" (zero) + \li The index of "Item 4", the new item added to the view \row - \o ViewTransition.targetItems - \o object array, just contains the "Item 4" delegate instance - \o The "Item 4" \l Rectangle object - the new item added to the view + \li ViewTransition.targetItems + \li object array, just contains the "Item 4" delegate instance + \li The "Item 4" \l Rectangle object - the new item added to the view \endtable The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 9db2060d89..2590d4691f 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -1848,13 +1848,13 @@ QQuickListView::~QQuickListView() Valid values for \c highlightRangeMode are: \list - \o ListView.ApplyRange - the view attempts to maintain the highlight within the range. + \li ListView.ApplyRange - the view attempts to maintain the highlight within the range. However, the highlight can move outside of the range at the ends of the list or due to mouse interaction. - \o ListView.StrictlyEnforceRange - the highlight never moves outside of the range. + \li ListView.StrictlyEnforceRange - the highlight never moves outside of the range. The current item changes if a keyboard or mouse action would cause the highlight to move outside of the range. - \o ListView.NoHighlightRange - this is the default value. + \li ListView.NoHighlightRange - this is the default value. \endlist */ void QQuickListView::setHighlightFollowsCurrentItem(bool autoHighlight) @@ -1902,17 +1902,17 @@ void QQuickListView::setSpacing(qreal spacing) Possible values: \list - \o ListView.Horizontal - Items are laid out horizontally - \o ListView.Vertical (default) - Items are laid out vertically + \li ListView.Horizontal - Items are laid out horizontally + \li ListView.Vertical (default) - Items are laid out vertically \endlist \table \row - \o Horizontal orientation: + \li Horizontal orientation: \image ListViewHorizontal.png \row - \o Vertical orientation: + \li Vertical orientation: \image listview-highlight.png \endtable */ @@ -1948,8 +1948,8 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) Possible values: \list - \o Qt.LeftToRight (default) - Items will be laid out from left to right. - \o Qt.RightToLeft - Items will be laid out from right to let. + \li Qt.LeftToRight (default) - Items will be laid out from left to right. + \li Qt.RightToLeft - Items will be laid out from right to let. \endlist \sa ListView::effectiveLayoutDirection @@ -2020,9 +2020,9 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) \c section.property. This value can be one of: \list - \o ViewSection.FullString (default) - sections are created based on the + \li ViewSection.FullString (default) - sections are created based on the \c section.property value. - \o ViewSection.FirstCharacter - sections are created based on the first + \li ViewSection.FirstCharacter - sections are created based on the first character of the \c section.property value (for example, 'A', 'B', 'C' sections, etc. for an address book) \endlist @@ -2034,11 +2034,11 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) the labels are shown inline. This value can be a combination of: \list - \o ViewSection.InlineLabels - section labels are shown inline between + \li ViewSection.InlineLabels - section labels are shown inline between the item delegates separating sections (default). - \o ViewSection.CurrentLabelAtStart - the current section label sticks to the + \li ViewSection.CurrentLabelAtStart - the current section label sticks to the start of the view as it is moved. - \o ViewSection.NextLabelAtEnd - the next section label (beyond all visible + \li ViewSection.NextLabelAtEnd - the next section label (beyond all visible sections) sticks to the end of the view as it is moved. \note Enabling \c ViewSection.NextLabelAtEnd requires the view to scan ahead for the next section, which has performance implications, especially for slower models. @@ -2174,10 +2174,10 @@ void QQuickListView::setHighlightResizeDuration(int duration) The possible values are: \list - \o ListView.NoSnap (default) - the view stops anywhere within the visible area. - \o ListView.SnapToItem - the view settles with an item aligned with the start of + \li ListView.NoSnap (default) - the view stops anywhere within the visible area. + \li ListView.SnapToItem - the view settles with an item aligned with the start of the view. - \o ListView.SnapOneItem - the view settles no more than one item away from the first + \li ListView.SnapOneItem - the view settles no more than one item away from the first visible item at the time the mouse button is released. This mode is particularly useful for moving one page at a time. \endlist @@ -2254,9 +2254,9 @@ void QQuickListView::setSnapMode(SnapMode mode) It is applied to all items that are created when: \list - \o The view is first created - \o The view's \l model changes - \o The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass + \li The view is first created + \li The view's \l model changes + \li The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass \endlist For example, here is a view that specifies such a transition: @@ -2670,7 +2670,7 @@ void QQuickListView::geometryChanged(const QRectF &newGeometry, const QRectF &ol if keyNavigationWraps is true and it is currently at the end. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickListView::incrementCurrentIndex() { @@ -2690,7 +2690,7 @@ void QQuickListView::incrementCurrentIndex() if keyNavigationWraps is true and it is currently at the beginning. This method has no effect if the \l count is zero. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickListView::decrementCurrentIndex() { @@ -2879,12 +2879,12 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex \a mode: \list - \o ListView.Beginning - position item at the top (or left for horizontal orientation) of the view. - \o ListView.Center - position item in the center of the view. - \o ListView.End - position item at bottom (or right for horizontal orientation) of the view. - \o ListView.Visible - if any part of the item is visible then take no action, otherwise + \li ListView.Beginning - position item at the top (or left for horizontal orientation) of the view. + \li ListView.Center - position item in the center of the view. + \li ListView.End - position item at bottom (or right for horizontal orientation) of the view. + \li ListView.Visible - if any part of the item is visible then take no action, otherwise bring the item into view. - \o ListView.Contain - ensure the entire item is visible. If the item is larger than + \li ListView.Contain - ensure the entire item is visible. If the item is larger than the view the item is positioned at the top (or left for horizontal orientation) of the view. \endlist @@ -2897,7 +2897,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex the actual start of the view can vary based on the size of the delegates. The correct way to bring an item into view is with \c positionViewAtIndex. - \bold Note: methods should only be called after the Component has completed. To position + \b Note: methods should only be called after the Component has completed. To position the view at startup, this method should be called by Component.onCompleted. For example, to position the view at the end: @@ -2917,7 +2917,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex of the list does not cause all other items to be repositioned, and because the actual start of the view can vary based on the size of the delegates. - \bold Note: methods should only be called after the Component has completed. To position + \b Note: methods should only be called after the Component has completed. To position the view at startup, this method should be called by Component.onCompleted. For example, to position the view at the end on startup: @@ -2936,7 +2936,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex If the item is outside the visible area, -1 is returned, regardless of whether an item will exist at that point when scrolled into view. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ /*! @@ -2949,7 +2949,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex If the item is outside the visible area, null is returned, regardless of whether an item will exist at that point when scrolled into view. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ QQuickListViewAttached *QQuickListView::qmlAttachedProperties(QObject *obj) diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index bbc51a4d26..8877385b46 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -148,10 +148,10 @@ void QQuickLoaderPrivate::initResize() accordingly to become visible. \list - \o If an explicit size is not specified for the Loader, the Loader + \li If an explicit size is not specified for the Loader, the Loader is automatically resized to the size of the loaded item once the component is loaded. - \o If the size of the Loader is specified explicitly by setting + \li If the size of the Loader is specified explicitly by setting the width, height or by anchoring, the loaded item will be resized to the size of the Loader. \endlist @@ -162,14 +162,14 @@ void QQuickLoaderPrivate::initResize() \table \row - \o sizeloader.qml - \o sizeitem.qml + \li sizeloader.qml + \li sizeitem.qml \row - \o \snippet doc/src/snippets/qml/loader/sizeloader.qml 0 - \o \snippet doc/src/snippets/qml/loader/sizeitem.qml 0 + \li \snippet doc/src/snippets/qml/loader/sizeloader.qml 0 + \li \snippet doc/src/snippets/qml/loader/sizeitem.qml 0 \row - \o The red rectangle will be sized to the size of the root item. - \o The red rectangle will be 50x50, centered in the root item. + \li The red rectangle will be sized to the size of the root item. + \li The red rectangle will be 50x50, centered in the root item. \endtable @@ -182,11 +182,11 @@ void QQuickLoaderPrivate::initResize() \table \row - \o application.qml - \o MyItem.qml + \li application.qml + \li MyItem.qml \row - \o \snippet doc/src/snippets/qml/loader/connections.qml 0 - \o \snippet doc/src/snippets/qml/loader/MyItem.qml 0 + \li \snippet doc/src/snippets/qml/loader/connections.qml 0 + \li \snippet doc/src/snippets/qml/loader/MyItem.qml 0 \endtable Alternatively, since \c MyItem.qml is loaded within the scope of the @@ -209,11 +209,11 @@ void QQuickLoaderPrivate::initResize() \table \row - \o application.qml - \o KeyReader.qml + \li application.qml + \li KeyReader.qml \row - \o \snippet doc/src/snippets/qml/loader/focus.qml 0 - \o \snippet doc/src/snippets/qml/loader/KeyReader.qml 0 + \li \snippet doc/src/snippets/qml/loader/focus.qml 0 + \li \snippet doc/src/snippets/qml/loader/KeyReader.qml 0 \endtable Once \c KeyReader.qml is loaded, it accepts key events and sets @@ -428,7 +428,7 @@ void QQuickLoader::loadFromSourceComponent() the \a source component will be created with the initial \a properties set. Setting the initial property values of an instance of a component in this manner - will \bold{not} trigger any associated \l{Behavior}s. + will \b{not} trigger any associated \l{Behavior}s. Note that the cached \a properties will be cleared if the \l source or \l sourceComponent is changed after calling this function but prior to setting the loader \l active. @@ -436,7 +436,7 @@ void QQuickLoader::loadFromSourceComponent() Example: \table \row - \o + \li \qml // ExampleComponent.qml import QtQuick 2.0 @@ -456,7 +456,7 @@ void QQuickLoader::loadFromSourceComponent() } } \endqml - \o + \li \qml // example.qml import QtQuick 2.0 @@ -633,22 +633,22 @@ void QQuickLoaderPrivate::_q_sourceLoaded() This property holds the status of QML loading. It can be one of: \list - \o Loader.Null - the loader is inactive or no QML source has been set - \o Loader.Ready - the QML source has been loaded - \o Loader.Loading - the QML source is currently being loaded - \o Loader.Error - an error occurred while loading the QML source + \li Loader.Null - the loader is inactive or no QML source has been set + \li Loader.Ready - the QML source has been loaded + \li Loader.Loading - the QML source is currently being loaded + \li Loader.Error - an error occurred while loading the QML source \endlist Use this status to provide an update or respond to the status change in some way. For example, you could: \list - \o Trigger a state change: + \li Trigger a state change: \qml State { name: 'loaded'; when: loader.status == Loader.Ready } \endqml - \o Implement an \c onStatusChanged signal handler: + \li Implement an \c onStatusChanged signal handler: \qml Loader { id: loader @@ -656,7 +656,7 @@ void QQuickLoaderPrivate::_q_sourceLoaded() } \endqml - \o Bind to the status value: + \li Bind to the status value: \qml Text { text: loader.status == Loader.Ready ? 'Loaded' : 'Not loaded' } \endqml diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index efb804bd18..b8555124eb 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -556,8 +556,8 @@ QQuickMouseArea::~QQuickMouseArea() If hoverEnabled is true then these properties will be valid when: \list - \i no button is pressed, but the mouse is within the MouseArea (containsMouse is true). - \i a button is pressed and held, even if it has since moved out of the area. + \li no button is pressed, but the mouse is within the MouseArea (containsMouse is true). + \li a button is pressed and held, even if it has since moved out of the area. \endlist The coordinates are relative to the MouseArea. @@ -671,9 +671,9 @@ void QQuickMouseArea::setPropagateComposedEvents(bool prevent) It contains a bitwise combination of: \list - \o Qt.LeftButton - \o Qt.RightButton - \o Qt.MiddleButton + \li Qt.LeftButton + \li Qt.RightButton + \li Qt.MiddleButton \endlist The code below displays "right" when the right mouse buttons is pressed: @@ -1100,9 +1100,9 @@ void QQuickMouseArea::setHovered(bool h) The available buttons are: \list - \o Qt.LeftButton - \o Qt.RightButton - \o Qt.MiddleButton + \li Qt.LeftButton + \li Qt.RightButton + \li Qt.MiddleButton \endlist To accept more than one button the flags can be combined with the @@ -1174,10 +1174,10 @@ bool QQuickMouseArea::setPressed(bool p) \c drag provides a convenient way to make an item draggable. \list - \i \c drag.target specifies the id of the item to drag. - \i \c drag.active specifies if the target item is currently being dragged. - \i \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis) - \i \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes. + \li \c drag.target specifies the id of the item to drag. + \li \c drag.active specifies if the target item is currently being dragged. + \li \c drag.axis specifies whether dragging can be done horizontally (\c Drag.XAxis), vertically (\c Drag.YAxis), or both (\c Drag.XandYAxis) + \li \c drag.minimum and \c drag.maximum limit how far the target can be dragged along the corresponding axes. \endlist The following example displays a \l Rectangle that can be dragged along the X-axis. The opacity diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 7dd6ec0589..110cc6ad7a 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -108,9 +108,9 @@ void QQuickTouchPoint::setY(qreal y) These properties hold additional information about the current state of the touch point. \list - \i \c pressure is a value in the range of 0.0 to 1.0. - \i \c velocity is a vector with magnitude reported in pixels per second. - \i \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point. + \li \c pressure is a value in the range of 0.0 to 1.0. + \li \c velocity is a vector with magnitude reported in pixels per second. + \li \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point. \endlist Not all touch devices support velocity. If velocity is not supported, it will be reported @@ -235,11 +235,11 @@ void QQuickTouchPoint::setSceneY(qreal sceneY) MultiPointTouchArea can be used in two ways: \list - \o setting \c touchPoints to provide touch point objects with properties that can be bound to - \o using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers + \li setting \c touchPoints to provide touch point objects with properties that can be bound to + \li using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers \endlist - While a MultiPointTouchArea \i can take exclusive ownership of certain touch points, it is also possible to have + While a MultiPointTouchArea \e can take exclusive ownership of certain touch points, it is also possible to have multiple MultiPointTouchAreas active at the same time, each operating on a different set of touch points. \sa TouchPoint diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 0526187531..1fa0a90b28 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -466,7 +466,7 @@ void QQuickPathViewPrivate::regenerate() \snippet doc/src/snippets/qml/pathview/pathview.qml 1 - \bold Note that views do not enable \e clip automatically. If the view + \b Note that views do not enable \e clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set \e {clip: true} in order to have the out of view items clipped nicely. @@ -695,7 +695,7 @@ QQuickItem *QQuickPathView::currentItem() const Increments the current index. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickPathView::incrementCurrentIndex() { @@ -709,7 +709,7 @@ void QQuickPathView::incrementCurrentIndex() Decrements the current index. - \bold Note: methods should only be called after the Component has completed. + \b Note: methods should only be called after the Component has completed. */ void QQuickPathView::decrementCurrentIndex() { diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 674abdcfd8..6f79385d96 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE \ingroup qml-event-elements \brief The PinchEvent object provides information about a pinch event. - \bold {The PinchEvent element was added in QtQuick 1.1} + \b {The PinchEvent element was added in QtQuick 1.1} The \c center, \c startCenter, \c previousCenter properties provide the center position between the two touch points. @@ -81,9 +81,9 @@ QT_BEGIN_NAMESPACE These properties hold the position of the center point between the two touch points. \list - \o \c center is the current center point - \o \c previousCenter is the center point of the previous event. - \o \c startCenter is the center point when the gesture began + \li \c center is the current center point + \li \c previousCenter is the center point of the previous event. + \li \c startCenter is the center point when the gesture began \endlist */ @@ -94,8 +94,8 @@ QT_BEGIN_NAMESPACE These properties hold the scale factor determined by the change in distance between the two touch points. \list - \o \c scale is the current scale factor. - \o \c previousScale is the scale factor of the previous event. + \li \c scale is the current scale factor. + \li \c previousScale is the scale factor of the previous event. \endlist When a pinch gesture is started, the scale is 1.0. @@ -109,9 +109,9 @@ QT_BEGIN_NAMESPACE These properties hold the angle between the two touch points. \list - \o \c angle is the current angle between the two points in the range -180 to 180. - \o \c previousAngle is the angle of the previous event. - \o \c rotation is the total rotation since the pinch gesture started. + \li \c angle is the current angle between the two points in the range -180 to 180. + \li \c previousAngle is the angle of the previous event. + \li \c rotation is the total rotation since the pinch gesture started. \endlist When a pinch gesture is started, the rotation is 0.0. @@ -126,8 +126,8 @@ QT_BEGIN_NAMESPACE These properties provide the actual touch points generating the pinch. \list - \o \c point1 and \c point2 hold the current positions of the points. - \o \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched. + \li \c point1 and \c point2 hold the current positions of the points. + \li \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched. \endlist */ @@ -166,7 +166,7 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate() \brief The PinchArea item enables simple pinch gesture handling. \inherits Item - \bold {The PinchArea element was added in QtQuick 1.1} + \b {The PinchArea element was added in QtQuick 1.1} A PinchArea is an invisible item that is typically used in conjunction with a visible item in order to provide pinch gesture handling for that item. @@ -178,8 +178,8 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate() PinchArea can be used in two ways: \list - \o setting a \c pinch.target to provide automatic interaction with an element - \o using the onPinchStarted, onPinchUpdated and onPinchFinished handlers + \li setting a \c pinch.target to provide automatic interaction with an element + \li using the onPinchStarted, onPinchUpdated and onPinchFinished handlers \endlist \sa PinchEvent @@ -232,12 +232,12 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate() \c pinch provides a convenient way to make an item react to pinch gestures. \list - \i \c pinch.target specifies the id of the item to drag. - \i \c pinch.active specifies if the target item is currently being dragged. - \i \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property. - \i \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property. - \i \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis) - \i \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes. + \li \c pinch.target specifies the id of the item to drag. + \li \c pinch.active specifies if the target item is currently being dragged. + \li \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property. + \li \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property. + \li \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis) + \li \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes. \endlist */ diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 7c4cd18346..97a74c6765 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -608,8 +608,8 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) positioner. For a positioner, this applies to: \list - \o Items that are created or reparented as a child of the positioner - \o Child items that change their \l visible property from false to true, and thus + \li Items that are created or reparented as a child of the positioner + \li Child items that change their \l visible property from false to true, and thus are now visible \endlist @@ -626,9 +626,9 @@ void QQuickPositionerAttached::setIsLastItem(bool isLastItem) positioner. For a positioner, this applies to: \list - \o Child items that move when they are displaced due to the addition, removal or + \li Child items that move when they are displaced due to the addition, removal or rearrangement of other items in the positioner - \o Child items that are repositioned due to the resizing of other items in the positioner + \li Child items that are repositioned due to the resizing of other items in the positioner \endlist The transition can use the \l ViewTransition property to access more details about @@ -741,8 +741,8 @@ void QQuickColumn::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Items that are created or reparented as a child of the positioner - \o Child items that change their \l visible property from false to true, and thus + \li Items that are created or reparented as a child of the positioner + \li Child items that change their \l visible property from false to true, and thus are now visible \endlist @@ -759,9 +759,9 @@ void QQuickColumn::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Child items that move when they are displaced due to the addition, removal or + \li Child items that move when they are displaced due to the addition, removal or rearrangement of other items in the positioner - \o Child items that are repositioned due to the resizing of other items in the positioner + \li Child items that are repositioned due to the resizing of other items in the positioner \endlist The transition can use the \l ViewTransition property to access more details about @@ -795,9 +795,9 @@ QQuickRow::QQuickRow(QQuickItem *parent) Possible values: \list - \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set, + \li Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set, the left anchor remains to the left of the row. - \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set, + \li Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set, the right anchor remains to the right of the row. \endlist @@ -953,8 +953,8 @@ void QQuickRow::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Items that are created or reparented as a child of the positioner - \o Child items that change their \l visible property from false to true, and thus + \li Items that are created or reparented as a child of the positioner + \li Child items that change their \l visible property from false to true, and thus are now visible \endlist @@ -971,9 +971,9 @@ void QQuickRow::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Child items that move when they are displaced due to the addition, removal or + \li Child items that move when they are displaced due to the addition, removal or rearrangement of other items in the positioner - \o Child items that are repositioned due to the resizing of other items in the positioner + \li Child items that are repositioned due to the resizing of other items in the positioner \endlist The transition can use the \l ViewTransition property to access more details about @@ -1059,9 +1059,9 @@ void QQuickGrid::setRows(const int rows) Possible values are: \list - \o Grid.LeftToRight (default) - Items are positioned next to + \li Grid.LeftToRight (default) - Items are positioned next to each other in the \l layoutDirection, then wrapped to the next line. - \o Grid.TopToBottom - Items are positioned next to each + \li Grid.TopToBottom - Items are positioned next to each other from top to bottom, then wrapped to the next column. \endlist */ @@ -1131,10 +1131,10 @@ void QQuickGrid::setColumnSpacing(const qreal columnSpacing) Possible values are: \list - \o Qt.LeftToRight (default) - Items are positioned from the top to bottom, + \li Qt.LeftToRight (default) - Items are positioned from the top to bottom, and left to right. The flow direction is dependent on the \l Grid::flow property. - \o Qt.RightToLeft - Items are positioned from the top to bottom, + \li Qt.RightToLeft - Items are positioned from the top to bottom, and right to left. The flow direction is dependent on the \l Grid::flow property. \endlist @@ -1366,8 +1366,8 @@ void QQuickGrid::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Items that are created or reparented as a child of the positioner - \o Child items that change their \l visible property from false to true, and thus + \li Items that are created or reparented as a child of the positioner + \li Child items that change their \l visible property from false to true, and thus are now visible \endlist @@ -1384,9 +1384,9 @@ void QQuickGrid::reportConflictingAnchors() positioner. For a positioner, this applies to: \list - \o Child items that move when they are displaced due to the addition, removal or + \li Child items that move when they are displaced due to the addition, removal or rearrangement of other items in the positioner - \o Child items that are repositioned due to the resizing of other items in the positioner + \li Child items that are repositioned due to the resizing of other items in the positioner \endlist The transition can use the \l ViewTransition property to access more details about @@ -1435,10 +1435,10 @@ QQuickFlow::QQuickFlow(QQuickItem *parent) Possible values are: \list - \o Flow.LeftToRight (default) - Items are positioned next to + \li Flow.LeftToRight (default) - Items are positioned next to to each other according to the \l layoutDirection until the width of the Flow is exceeded, then wrapped to the next line. - \o Flow.TopToBottom - Items are positioned next to each + \li Flow.TopToBottom - Items are positioned next to each other from top to bottom until the height of the Flow is exceeded, then wrapped to the next column. \endlist @@ -1467,10 +1467,10 @@ void QQuickFlow::setFlow(Flow flow) Possible values are: \list - \o Qt.LeftToRight (default) - Items are positioned from the top to bottom, + \li Qt.LeftToRight (default) - Items are positioned from the top to bottom, and left to right. The flow direction is dependent on the \l Flow::flow property. - \o Qt.RightToLeft - Items are positioned from the top to bottom, + \li Qt.RightToLeft - Items are positioned from the top to bottom, and right to left. The flow direction is dependent on the \l Flow::flow property. \endlist diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 1f7578c583..f83b9f068a 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -162,10 +162,10 @@ QQuickRepeater::~QQuickRepeater() This property can be set to any of the supported \l {qmlmodels}{data models}: \list - \o A number that indicates the number of delegates to be created by the repeater - \o A model (e.g. a ListModel item, or a QAbstractItemModel subclass) - \o A string list - \o An object list + \li A number that indicates the number of delegates to be created by the repeater + \li A model (e.g. a ListModel item, or a QAbstractItemModel subclass) + \li A string list + \li An object list \endlist The type of model affects the properties that are exposed to the \l delegate. @@ -243,8 +243,8 @@ void QQuickRepeater::setModel(const QVariant &model) \table \row - \o \snippet doc/src/snippets/qml/repeaters/repeater.qml index - \o \image repeater-index.png + \li \snippet doc/src/snippets/qml/repeaters/repeater.qml index + \li \image repeater-index.png \endtable If the \l model is a \l{QStringList-based model}{string list} or @@ -254,8 +254,8 @@ void QQuickRepeater::setModel(const QVariant &model) \table \row - \o \snippet doc/src/snippets/qml/repeaters/repeater.qml modeldata - \o \image repeater-modeldata.png + \li \snippet doc/src/snippets/qml/repeaters/repeater.qml modeldata + \li \image repeater-modeldata.png \endtable If the \l model is a model object (such as a \l ListModel) the delegate diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 3024c31d51..77047257c3 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -103,15 +103,15 @@ const char *qtTexCoordAttributeName() There are two types of input to the \l vertexShader: uniform variables and attributes. Some are predefined: \list - \o uniform mat4 qt_Matrix - combined transformation + \li uniform mat4 qt_Matrix - combined transformation matrix, the product of the matrices from the root item to this ShaderEffect, and an orthogonal projection. - \o uniform float qt_Opacity - combined opacity, the product of the + \li uniform float qt_Opacity - combined opacity, the product of the opacities from the root item to this ShaderEffect. - \o attribute vec4 qt_Vertex - vertex position, the top-left vertex has + \li attribute vec4 qt_Vertex - vertex position, the top-left vertex has position (0, 0), the bottom-right (\l{Item::width}{width}, \l{Item::height}{height}). - \o attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left + \li attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left coordinate is (0, 0), the bottom-right (1, 1). \endlist @@ -119,17 +119,17 @@ const char *qtTexCoordAttributeName() (GLSL) type is available as a uniform variable. The following list shows how properties are mapped to GLSL uniform variables: \list - \o bool, int, qreal -> bool, int, float - If the type in the shader is not + \li bool, int, qreal -> bool, int, float - If the type in the shader is not the same as in QML, the value is converted automatically. - \o QColor -> vec4 - When colors are passed to the shader, they are first + \li QColor -> vec4 - When colors are passed to the shader, they are first premultiplied. Thus Qt.rgba(0.2, 0.6, 1.0, 0.5) becomes vec4(0.1, 0.3, 0.5, 0.5) in the shader, for example. - \o QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in + \li QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in the shader. - \o QPoint, QPointF, QSize, QSizeF -> vec2 - \o QVector3D -> vec3 - \o QTransform -> mat4 - \o \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left + \li QPoint, QPointF, QSize, QSizeF -> vec2 + \li QVector3D -> vec3 + \li QTransform -> mat4 + \li \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left corner, and the color values are premultiplied. \endlist @@ -138,8 +138,8 @@ const char *qtTexCoordAttributeName() blending can be achieved by outputting zero in the alpha channel. \row - \o \image declarative-shadereffectitem.png - \o \qml + \li \image declarative-shadereffectitem.png + \li \qml import QtQuick 2.0 Rectangle { @@ -326,9 +326,9 @@ void QQuickShaderEffect::setMesh(const QVariant &mesh) This property defines which sides of the element should be visible. \list - \o ShaderEffect.NoCulling - Both sides are visible - \o ShaderEffect.BackFaceCulling - only front side is visible - \o ShaderEffect.FrontFaceCulling - only back side is visible + \li ShaderEffect.NoCulling - Both sides are visible + \li ShaderEffect.BackFaceCulling - only front side is visible + \li ShaderEffect.FrontFaceCulling - only back side is visible \endlist The default is NoCulling. @@ -349,9 +349,9 @@ void QQuickShaderEffect::setCullMode(CullMode face) This property tells the current status of the OpenGL shader program. \list - \o ShaderEffect.Compiled - the shader program was successfully compiled and linked. - \o ShaderEffect.Uncompiled - the shader program has not yet been compiled. - \o ShaderEffect.Error - the shader program failed to compile or link. + \li ShaderEffect.Compiled - the shader program was successfully compiled and linked. + \li ShaderEffect.Uncompiled - the shader program has not yet been compiled. + \li ShaderEffect.Error - the shader program failed to compile or link. \endlist When setting the fragment or vertex shader source code, the status will become Uncompiled. diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp index eff5910a09..582e1ce92f 100644 --- a/src/quick/items/qquickshadereffectmesh.cpp +++ b/src/quick/items/qquickshadereffectmesh.cpp @@ -169,8 +169,8 @@ QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector resolution higher. \row - \o \image declarative-gridmesh.png - \o \qml + \li \image declarative-gridmesh.png + \li \qml import QtQuick 2.0 ShaderEffect { diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index 708d75d137..33776be712 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -413,21 +413,21 @@ QImage QQuickShaderEffectTexture::toImage() const ShaderEffectSource can be used as: \list - \o a texture source in a \l ShaderEffect. + \li a texture source in a \l ShaderEffect. This allows you to apply custom shader effects to any QML element. - \o a cache for a complex element. + \li a cache for a complex element. The complex element can be rendered once into the texture, which can then be animated freely without the need to render the complex element again every frame. - \o an opacity layer. + \li an opacity layer. ShaderEffectSource allows you to apply an opacity to elements as a group rather than each element individually. \endlist \table \row - \o \image declarative-shadereffectsource.png - \o \qml + \li \image declarative-shadereffectsource.png + \li \qml import QtQuick 2.0 Rectangle { @@ -548,10 +548,10 @@ QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const source texture of a \l ShaderEffect. \list - \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically - \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically - \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically - \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically + \li ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically + \li ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically + \li ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically + \li ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically \endlist \note Some OpenGL ES 2 implementations do not support the GL_REPEAT @@ -677,9 +677,9 @@ void QQuickShaderEffectSource::setTextureSize(const QSize &size) implementation, this property might allow you to save some texture memory. \list - \o ShaderEffectSource.Alpha - GL_ALPHA - \o ShaderEffectSource.RGB - GL_RGB - \o ShaderEffectSource.RGBA - GL_RGBA + \li ShaderEffectSource.Alpha - GL_ALPHA + \li ShaderEffectSource.RGB - GL_RGB + \li ShaderEffectSource.RGBA - GL_RGBA \endlist \note Some OpenGL implementations do not support the GL_ALPHA format. diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 36b902ff8c..9f22dfdd08 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -1176,11 +1176,11 @@ QQuickText::~QQuickText() The properties of a line are: \list - \o number (read-only) - \o x - \o y - \o width - \o height + \li number (read-only) + \li x + \li y + \li width + \li height \endlist For example, this will move the first 5 lines of a text element by 100 pixels to the right: @@ -1233,11 +1233,11 @@ QQuickText::~QQuickText() The weight can be one of: \list - \o Font.Light - \o Font.Normal - the default - \o Font.DemiBold - \o Font.Bold - \o Font.Black + \li Font.Light + \li Font.Normal - the default + \li Font.DemiBold + \li Font.Bold + \li Font.Black \endlist \qml @@ -1303,11 +1303,11 @@ QQuickText::~QQuickText() Sets the capitalization for the text. \list - \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. - \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. - \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. - \o Font.SmallCaps - This alters the text to be rendered in small-caps type. - \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \li Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. + \li Font.AllUppercase - This alters the text to be rendered in all uppercase type. + \li Font.AllLowercase - This alters the text to be rendered in all lowercase type. + \li Font.SmallCaps - This alters the text to be rendered in small-caps type. + \li Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. \endlist \qml @@ -1464,10 +1464,10 @@ void QQuickText::setLinkColor(const QColor &color) Supported text styles are: \list - \o Text.Normal - the default - \o Text.Outline - \o Text.Raised - \o Text.Sunken + \li Text.Normal - the default + \li Text.Outline + \li Text.Raised + \li Text.Sunken \endlist \qml @@ -1661,10 +1661,10 @@ void QQuickText::setVAlign(VAlignment align) wrap if an explicit width has been set. wrapMode can be one of: \list - \o Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l contentWidth will exceed a set width. - \o Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l contentWidth will exceed a set width. - \o Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. - \o Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. + \li Text.NoWrap (default) - no wrapping will be performed. If the text contains insufficient newlines, then \l contentWidth will exceed a set width. + \li Text.WordWrap - wrapping is done on word boundaries only. If a word is too long, \l contentWidth will exceed a set width. + \li Text.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \li Text.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist */ QQuickText::WrapMode QQuickText::wrapMode() const @@ -1763,10 +1763,10 @@ void QQuickText::resetMaximumLineCount() Supported text formats are: \list - \o Text.AutoText (default) - \o Text.PlainText - \o Text.StyledText - \o Text.RichText + \li Text.AutoText (default) + \li Text.PlainText + \li Text.StyledText + \li Text.RichText \endlist If the text format is \c Text.AutoText the text element @@ -1800,7 +1800,7 @@ void QQuickText::resetMaximumLineCount() \table \row - \o + \li \qml Column { Text { @@ -1819,7 +1819,7 @@ Column { } } \endqml - \o \image declarative-textformat.png + \li \image declarative-textformat.png \endtable */ QQuickText::TextFormat QQuickText::textFormat() const @@ -1863,10 +1863,10 @@ void QQuickText::setTextFormat(TextFormat format) Eliding can be: \list - \o Text.ElideNone - the default - \o Text.ElideLeft - \o Text.ElideMiddle - \o Text.ElideRight + \li Text.ElideNone - the default + \li Text.ElideLeft + \li Text.ElideMiddle + \li Text.ElideRight \endlist If this property is set to Text.ElideRight, it can be used with \l {wrapMode}{wrapped} @@ -1908,14 +1908,14 @@ void QQuickText::setElideMode(QQuickText::TextElideMode mode) URL meaning any portion of the path after the last '/' will be ignored. \table - \header \o Base URL \o Relative URL \o Resolved URL - \row \o http://qt-project.org/ \o images/logo.png \o http://qt-project.org/images/logo.png - \row \o http://qt-project.org/index.html \o images/logo.png \o http://qt-project.org/images/logo.png - \row \o http://qt-project.org/content \o images/logo.png \o http://qt-project.org/content/images/logo.png - \row \o http://qt-project.org/content/ \o images/logo.png \o http://qt-project.org/content/images/logo.png - \row \o http://qt-project.org/content/index.html \o images/logo.png \o http://qt-project.org/content/images/logo.png - \row \o http://qt-project.org/content/index.html \o ../images/logo.png \o http://qt-project.org/images/logo.png - \row \o http://qt-project.org/content/index.html \o /images/logo.png \o http://qt-project.org/images/logo.png + \header \li Base URL \li Relative URL \li Resolved URL + \row \li http://qt-project.org/ \li images/logo.png \li http://qt-project.org/images/logo.png + \row \li http://qt-project.org/index.html \li images/logo.png \li http://qt-project.org/images/logo.png + \row \li http://qt-project.org/content \li images/logo.png \li http://qt-project.org/content/images/logo.png + \row \li http://qt-project.org/content/ \li images/logo.png \li http://qt-project.org/content/images/logo.png + \row \li http://qt-project.org/content/index.html \li images/logo.png \li http://qt-project.org/content/images/logo.png + \row \li http://qt-project.org/content/index.html \li ../images/logo.png \li http://qt-project.org/images/logo.png + \row \li http://qt-project.org/content/index.html \li /images/logo.png \li http://qt-project.org/images/logo.png \endtable By default is the url of the Text element. @@ -2169,9 +2169,9 @@ void QQuickText::setLineHeight(qreal lineHeight) The possible values are: \list - \o Text.ProportionalHeight (default) - this sets the spacing proportional to the + \li Text.ProportionalHeight (default) - this sets the spacing proportional to the line (as a multiplier). For example, set to 2 for double spacing. - \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels). + \li Text.FixedHeight - this sets the line height to a fixed line height (in pixels). \endlist */ QQuickText::LineHeightMode QQuickText::lineHeightMode() const @@ -2199,13 +2199,13 @@ void QQuickText::setLineHeightMode(LineHeightMode mode) The possible values are: \list - \o Text.FixedSize (default) - The size specified by \l font.pixelSize + \li Text.FixedSize (default) - The size specified by \l font.pixelSize or \l font.pointSize is used. - \o Text.HorizontalFit - The largest size up to the size specified that fits + \li Text.HorizontalFit - The largest size up to the size specified that fits within the width of the item without wrapping is used. - \o Text.VerticalFit - The largest size up to the size specified that fits + \li Text.VerticalFit - The largest size up to the size specified that fits the height of the item is used. - \o Text.Fit - The largest size up to the size specified the fits within the + \li Text.Fit - The largest size up to the size specified the fits within the width and height of the item is used. \endlist diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 3db5f5a7a3..5456d3523a 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -159,11 +159,11 @@ QString QQuickTextEdit::text() const The weight can be one of: \list - \o Font.Light - \o Font.Normal - the default - \o Font.DemiBold - \o Font.Bold - \o Font.Black + \li Font.Light + \li Font.Normal - the default + \li Font.DemiBold + \li Font.Bold + \li Font.Black \endlist \qml @@ -230,11 +230,11 @@ QString QQuickTextEdit::text() const Sets the capitalization for the text. \list - \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. - \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. - \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. - \o Font.SmallCaps - This alters the text to be rendered in small-caps type. - \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \li Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. + \li Font.AllUppercase - This alters the text to be rendered in all uppercase type. + \li Font.AllLowercase - This alters the text to be rendered in all lowercase type. + \li Font.SmallCaps - This alters the text to be rendered in small-caps type. + \li Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. \endlist \qml @@ -274,9 +274,9 @@ void QQuickTextEdit::setText(const QString &text) The way the text property should be displayed. \list - \o TextEdit.AutoText - \o TextEdit.PlainText - \o TextEdit.RichText + \li TextEdit.AutoText + \li TextEdit.PlainText + \li TextEdit.RichText \endlist The default is TextEdit.PlainText. If the text format is TextEdit.AutoText the text edit @@ -285,7 +285,7 @@ void QQuickTextEdit::setText(const QString &text) \table \row - \o + \li \qml Column { TextEdit { @@ -304,7 +304,7 @@ Column { } } \endqml - \o \image declarative-textformat.png + \li \image declarative-textformat.png \endtable */ QQuickTextEdit::TextFormat QQuickTextEdit::textFormat() const @@ -459,17 +459,17 @@ void QQuickTextEdit::setSelectedTextColor(const QColor &color) Valid values for \c horizontalAlignment are: \list - \o TextEdit.AlignLeft (default) - \o TextEdit.AlignRight - \o TextEdit.AlignHCenter - \o TextEdit.AlignJustify + \li TextEdit.AlignLeft (default) + \li TextEdit.AlignRight + \li TextEdit.AlignHCenter + \li TextEdit.AlignJustify \endlist Valid values for \c verticalAlignment are: \list - \o TextEdit.AlignTop (default) - \o TextEdit.AlignBottom - \o TextEdit.AlignVCenter + \li TextEdit.AlignTop (default) + \li TextEdit.AlignBottom + \li TextEdit.AlignVCenter \endlist When using the attached property LayoutMirroring::enabled to mirror application @@ -591,10 +591,10 @@ void QQuickTextEdit::setVAlign(QQuickTextEdit::VAlignment alignment) The text will only wrap if an explicit width has been set. \list - \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. - \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. - \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. - \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. + \li TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \li TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \li TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \li TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap. @@ -770,9 +770,9 @@ int QQuickTextEdit::positionAt(qreal x, qreal y) const basis. If not specified the selection mode will default to TextEdit.SelectCharacters. \list - \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + \li TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at the previous cursor position) to the specified position. - \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all + \li TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all words between the specified position and the previous cursor position. Words partially in the range are included. \endlist @@ -1089,36 +1089,36 @@ void QQuickTextEdit::setTextMargin(qreal margin) Flags that alter behaviour are: \list - \o Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords. - \o Qt.ImhSensitiveData - Typed text should not be stored by the active input method + \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords. + \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method in any persistent storage like predictive user dictionary. - \o Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case + \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case when a sentence ends. - \o Qt.ImhPreferNumbers - Numbers are preferred (but not required). - \o Qt.ImhPreferUppercase - Upper case letters are preferred (but not required). - \o Qt.ImhPreferLowercase - Lower case letters are preferred (but not required). - \o Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing. + \li Qt.ImhPreferNumbers - Numbers are preferred (but not required). + \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required). + \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required). + \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing. - \o Qt.ImhDate - The text editor functions as a date field. - \o Qt.ImhTime - The text editor functions as a time field. + \li Qt.ImhDate - The text editor functions as a date field. + \li Qt.ImhTime - The text editor functions as a time field. \endlist Flags that restrict input (exclusive flags) are: \list - \o Qt.ImhDigitsOnly - Only digits are allowed. - \o Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign. - \o Qt.ImhUppercaseOnly - Only upper case letter input is allowed. - \o Qt.ImhLowercaseOnly - Only lower case letter input is allowed. - \o Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed. - \o Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed. - \o Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed. + \li Qt.ImhDigitsOnly - Only digits are allowed. + \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign. + \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed. + \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed. + \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed. + \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed. + \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed. \endlist Masks: \list - \o Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used. + \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used. \endlist */ @@ -1203,8 +1203,8 @@ void QQuickTextEdit::setSelectByMouse(bool on) Specifies how text should be selected using a mouse. \list - \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default) - \o TextEdit.SelectWords - The selection is updated with whole words. + \li TextEdit.SelectCharacters - The selection is updated with individual characters. (Default) + \li TextEdit.SelectWords - The selection is updated with whole words. \endlist This property only applies when \l selectByMouse is true. diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 3b62e99557..a353d0c91f 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -201,11 +201,11 @@ QString QQuickTextInputPrivate::realText() const The weight can be one of: \list - \o Font.Light - \o Font.Normal - the default - \o Font.DemiBold - \o Font.Bold - \o Font.Black + \li Font.Light + \li Font.Normal - the default + \li Font.DemiBold + \li Font.Bold + \li Font.Black \endlist \qml @@ -271,11 +271,11 @@ QString QQuickTextInputPrivate::realText() const Sets the capitalization for the text. \list - \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. - \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. - \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. - \o Font.SmallCaps - This alters the text to be rendered in small-caps type. - \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. + \li Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. + \li Font.AllUppercase - This alters the text to be rendered in all uppercase type. + \li Font.AllLowercase - This alters the text to be rendered in all lowercase type. + \li Font.SmallCaps - This alters the text to be rendered in small-caps type. + \li Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. \endlist \qml @@ -512,10 +512,10 @@ void QQuickTextInput::setVAlign(QQuickTextInput::VAlignment alignment) The text will only wrap if an explicit width has been set. \list - \o TextInput.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. - \o TextInput.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. - \o TextInput.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. - \o TextInput.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. + \li TextInput.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width. + \li TextInput.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width. + \li TextInput.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word. + \li TextInput.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word. \endlist The default is TextInput.NoWrap. If you set a width, consider using TextInput.Wrap. @@ -958,8 +958,8 @@ void QQuickDoubleValidator::resetLocaleName() The possible values for this property are: \list - \o DoubleValidator.StandardNotation - \o DoubleValidator.ScientificNotation (default) + \li DoubleValidator.StandardNotation + \li DoubleValidator.ScientificNotation (default) \endlist If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2). @@ -1110,10 +1110,10 @@ Qt::InputMethodHints QQuickTextInputPrivate::effectiveInputMethodHints() const Specifies how the text should be displayed in the TextInput. \list - \o TextInput.Normal - Displays the text as it is. (Default) - \o TextInput.Password - Displays asterisks instead of characters. - \o TextInput.NoEcho - Displays nothing. - \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered + \li TextInput.Normal - Displays the text as it is. (Default) + \li TextInput.Password - Displays asterisks instead of characters. + \li TextInput.NoEcho - Displays nothing. + \li TextInput.PasswordEchoOnEdit - Displays characters as they are entered while editing, otherwise displays asterisks. \endlist */ @@ -1149,37 +1149,37 @@ void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo) Flags that alter behaviour are: \list - \o Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords. + \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords. This is automatically set when setting echoMode to \c TextInput.Password. - \o Qt.ImhSensitiveData - Typed text should not be stored by the active input method + \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method in any persistent storage like predictive user dictionary. - \o Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case + \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case when a sentence ends. - \o Qt.ImhPreferNumbers - Numbers are preferred (but not required). - \o Qt.ImhPreferUppercase - Upper case letters are preferred (but not required). - \o Qt.ImhPreferLowercase - Lower case letters are preferred (but not required). - \o Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing. + \li Qt.ImhPreferNumbers - Numbers are preferred (but not required). + \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required). + \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required). + \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing. - \o Qt.ImhDate - The text editor functions as a date field. - \o Qt.ImhTime - The text editor functions as a time field. + \li Qt.ImhDate - The text editor functions as a date field. + \li Qt.ImhTime - The text editor functions as a time field. \endlist Flags that restrict input (exclusive flags) are: \list - \o Qt.ImhDigitsOnly - Only digits are allowed. - \o Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign. - \o Qt.ImhUppercaseOnly - Only upper case letter input is allowed. - \o Qt.ImhLowercaseOnly - Only lower case letter input is allowed. - \o Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed. - \o Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed. - \o Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed. + \li Qt.ImhDigitsOnly - Only digits are allowed. + \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign. + \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed. + \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed. + \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed. + \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed. + \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed. \endlist Masks: \list - \o Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used. + \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used. \endlist */ @@ -1323,8 +1323,8 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const The cursor position type specifies how the cursor position should be resolved. \list - \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x. - \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x. + \li TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x. + \li TextInput.CursorOnCharacter - Returns the position before the character that is nearest x. \endlist */ @@ -2161,8 +2161,8 @@ void QQuickTextInput::setSelectByMouse(bool on) Specifies how text should be selected using a mouse. \list - \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default) - \o TextInput.SelectWords - The selection is updated with whole words. + \li TextInput.SelectCharacters - The selection is updated with individual characters. (Default) + \li TextInput.SelectWords - The selection is updated with whole words. \endlist This property only applies when \l selectByMouse is true. @@ -2295,9 +2295,9 @@ void QQuickTextInput::moveCursorSelection(int position) basis. If not specified the selection mode will default to TextInput.SelectCharacters. \list - \o TextInput.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + \li TextInput.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at the previous cursor position) to the specified position. - \o TextInput.SelectWords - Sets the selectionStart and selectionEnd to include all + \li TextInput.SelectWords - Sets the selectionStart and selectionEnd to include all words between the specified position and the previous cursor position. Words partially in the range are included. \endlist diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 70f8897b2d..97d137202a 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -1891,16 +1891,16 @@ void QQuickVisualDataGroup::setDefaultInclude(bool include) VisualDataModel attached as well as the model for that item. It has the properties: \list - \o \b model The model data of the item. This is the same as the model context property in + \li \b model The model data of the item. This is the same as the model context property in a delegate - \o \b groups A list the of names of groups the item is a member of. This property can be + \li \b groups A list the of names of groups the item is a member of. This property can be written to change the item's membership. - \o \b inItems Whether the item belongs to the \l {QtQuick2::VisualDataModel::items}{items} group. + \li \b inItems Whether the item belongs to the \l {QtQuick2::VisualDataModel::items}{items} group. Writing to this property will add or remove the item from the group. - \o \b itemsIndex The index of the item within the \l {QtQuick2::VisualDataModel::items}{items} group. - \o \b {in\i{GroupName}} Whether the item belongs to the dynamic group \i groupName. Writing to + \li \b itemsIndex The index of the item within the \l {QtQuick2::VisualDataModel::items}{items} group. + \li \b {in\e{GroupName}} Whether the item belongs to the dynamic group \e groupName. Writing to this property will add or remove the item from the group. - \o \b {\i{groupName}Index} The index of the item within the dynamic group \i groupName. + \li \b {\e{groupName}Index} The index of the item within the dynamic group \e groupName. \endlist */ diff --git a/src/quick/particles/qquickimageparticle.cpp b/src/quick/particles/qquickimageparticle.cpp index ae1688b94d..386892a12a 100644 --- a/src/quick/particles/qquickimageparticle.cpp +++ b/src/quick/particles/qquickimageparticle.cpp @@ -591,10 +591,10 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size) This element renders a logical particle as an image. The image can be \list - \o colorized - \o rotated - \o deformed - \o a sprite-based animation + \li colorized + \li rotated + \li deformed + \li a sprite-based animation \endlist ImageParticles implictly share data on particles if multiple ImageParticles are painting @@ -770,9 +770,9 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size) Acceptable values are \list - \o ImageParticle.None: Particles just appear and disappear. - \o ImageParticle.Fade: Particles fade in from 0 opacity at the start of their life, and fade out to 0 at the end. - \o ImageParticle.Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end. + \li ImageParticle.None: Particles just appear and disappear. + \li ImageParticle.Fade: Particles fade in from 0 opacity at the start of their life, and fade out to 0 at the end. + \li ImageParticle.Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end. \endlist Default value is Fade. diff --git a/src/quick/particles/qquickpointattractor.cpp b/src/quick/particles/qquickpointattractor.cpp index 7cb8c32671..a54ee41c1e 100644 --- a/src/quick/particles/qquickpointattractor.cpp +++ b/src/quick/particles/qquickpointattractor.cpp @@ -85,9 +85,9 @@ QT_BEGIN_NAMESPACE What attribute of particles is directly affected. \list - \o Attractor.Position - \o Attractor.Velocity - \o Attractor.Acceleration + \li Attractor.Position + \li Attractor.Velocity + \li Attractor.Acceleration \endlist */ /*! @@ -96,11 +96,11 @@ QT_BEGIN_NAMESPACE How the distance from the particle to the point affects the strength of the attraction. \list - \o Attractor.Constant - \o Attractor.Linear - \o Attractor.InverseLinear - \o Attractor.Quadratic - \o Attractor.InverseQuadratic + \li Attractor.Constant + \li Attractor.Linear + \li Attractor.InverseLinear + \li Attractor.Quadratic + \li Attractor.InverseQuadratic \endlist */ diff --git a/src/quick/particles/qquickwander.cpp b/src/quick/particles/qquickwander.cpp index 3e7cf33a64..0f9a5f069b 100644 --- a/src/quick/particles/qquickwander.cpp +++ b/src/quick/particles/qquickwander.cpp @@ -73,9 +73,9 @@ QT_BEGIN_NAMESPACE What attribute of particles is directly affected. \list - \o PointAttractor.Position - \o PointAttractor.Velocity - \o PointAttractor.Acceleration + \li PointAttractor.Position + \li PointAttractor.Velocity + \li PointAttractor.Acceleration \endlist */ diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp index ee9fd9fbbb..8012af9cfc 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@ -63,14 +63,14 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity) This function should return a mask where each bit represents OpenGL states changed by the \l render() function: \list - \o DepthState - depth write mask, depth test enabled, depth comparison function - \o StencilState - stencil write masks, stencil test enabled, stencil operations, + \li DepthState - depth write mask, depth test enabled, depth comparison function + \li StencilState - stencil write masks, stencil test enabled, stencil operations, stencil comparison functions - \o ScissorState - scissor enabled, scissor test enabled - \o ColorState - clear color, color write mask - \o BlendState - blend enabled, blend function - \o CullState - front face, cull face enabled - \o ViewportState - viewport + \li ScissorState - scissor enabled, scissor test enabled + \li ColorState - clear color, color write mask + \li BlendState - blend enabled, blend function + \li CullState - front face, cull face enabled + \li ViewportState - viewport \endlist The function is called by the renderer so it can reset the OpenGL states after rendering this @@ -96,17 +96,17 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity) The following states are set before this function is called: \list - \o glDepthMask(false) - \o glDisable(GL_DEPTH_TEST) - \o glStencilMask(0) - \o glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip - \o glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip - \o glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip - \o glScissor(state.scissorRect.x(), state.scissorRect.y(), + \li glDepthMask(false) + \li glDisable(GL_DEPTH_TEST) + \li glStencilMask(0) + \li glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip + \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip + \li glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip + \li glScissor(state.scissorRect.x(), state.scissorRect.y(), state.scissorRect.width(), state.scissorRect.height()) depending on clip - \o glEnable(GL_BLEND) - \o glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) - \o glDisable(GL_CULL_FACE) + \li glEnable(GL_BLEND) + \li glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) + \li glDisable(GL_CULL_FACE) \endlist States that are not listed above, but are included in \l StateFlags, can have arbitrary diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index 51b598b28d..33a5d0a438 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -1536,11 +1536,11 @@ void QQuickRotationAnimation::setTo(qreal t) Possible values are: \list - \o RotationAnimation.Numerical (default) - Rotate by linearly interpolating between the two numbers. + \li RotationAnimation.Numerical (default) - Rotate by linearly interpolating between the two numbers. A rotation from 10 to 350 will rotate 340 degrees clockwise. - \o RotationAnimation.Clockwise - Rotate clockwise between the two values - \o RotationAnimation.Counterclockwise - Rotate counterclockwise between the two values - \o RotationAnimation.Shortest - Rotate in the direction that produces the shortest animation path. + \li RotationAnimation.Clockwise - Rotate clockwise between the two values + \li RotationAnimation.Counterclockwise - Rotate counterclockwise between the two values + \li RotationAnimation.Shortest - Rotate in the direction that produces the shortest animation path. A rotation from 10 to 350 will rotate 20 degrees counterclockwise. \endlist */ @@ -1846,7 +1846,7 @@ void QQuickBulkValueAnimator::topLevelAnimationLoopChanged() It can be used to define animations in a number of ways: \list - \o In a \l Transition + \li In a \l Transition For example, to animate any objects that have changed their \c x or \c y properties as a result of a state change, using an \c InOutQuad easing curve: @@ -1854,21 +1854,21 @@ void QQuickBulkValueAnimator::topLevelAnimationLoopChanged() \snippet doc/src/snippets/qml/propertyanimation.qml transition - \o In a \l Behavior + \li In a \l Behavior For example, to animate all changes to a rectangle's \c x property: \snippet doc/src/snippets/qml/propertyanimation.qml behavior - \o As a property value source + \li As a property value source For example, to repeatedly animate the rectangle's \c x property: \snippet doc/src/snippets/qml/propertyanimation.qml propertyvaluesource - \o In a signal handler + \li In a signal handler For example, to fade out \c theObject when clicked: \qml @@ -1878,7 +1878,7 @@ void QQuickBulkValueAnimator::topLevelAnimationLoopChanged() } \endqml - \o Standalone + \li Standalone For example, to animate \c rect's \c width property over 500ms, from its current width to 30: @@ -2010,175 +2010,175 @@ void QQuickPropertyAnimation::setTo(const QVariant &t) \table \row - \o \c Easing.Linear - \o Easing curve for a linear (t) function: velocity is constant. - \o \inlineimage qeasingcurve-linear.png + \li \c Easing.Linear + \li Easing curve for a linear (t) function: velocity is constant. + \li \inlineimage qeasingcurve-linear.png \row - \o \c Easing.InQuad - \o Easing curve for a quadratic (t^2) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inquad.png + \li \c Easing.InQuad + \li Easing curve for a quadratic (t^2) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inquad.png \row - \o \c Easing.OutQuad - \o Easing curve for a quadratic (t^2) function: decelerating to zero velocity. - \o \inlineimage qeasingcurve-outquad.png + \li \c Easing.OutQuad + \li Easing curve for a quadratic (t^2) function: decelerating to zero velocity. + \li \inlineimage qeasingcurve-outquad.png \row - \o \c Easing.InOutQuad - \o Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutquad.png + \li \c Easing.InOutQuad + \li Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutquad.png \row - \o \c Easing.OutInQuad - \o Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinquad.png + \li \c Easing.OutInQuad + \li Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinquad.png \row - \o \c Easing.InCubic - \o Easing curve for a cubic (t^3) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-incubic.png + \li \c Easing.InCubic + \li Easing curve for a cubic (t^3) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-incubic.png \row - \o \c Easing.OutCubic - \o Easing curve for a cubic (t^3) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outcubic.png + \li \c Easing.OutCubic + \li Easing curve for a cubic (t^3) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outcubic.png \row - \o \c Easing.InOutCubic - \o Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutcubic.png + \li \c Easing.InOutCubic + \li Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutcubic.png \row - \o \c Easing.OutInCubic - \o Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outincubic.png + \li \c Easing.OutInCubic + \li Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outincubic.png \row - \o \c Easing.InQuart - \o Easing curve for a quartic (t^4) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inquart.png + \li \c Easing.InQuart + \li Easing curve for a quartic (t^4) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inquart.png \row - \o \c Easing.OutQuart - \o Easing curve for a quartic (t^4) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outquart.png + \li \c Easing.OutQuart + \li Easing curve for a quartic (t^4) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outquart.png \row - \o \c Easing.InOutQuart - \o Easing curve for a quartic (t^4) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutquart.png + \li \c Easing.InOutQuart + \li Easing curve for a quartic (t^4) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutquart.png \row - \o \c Easing.OutInQuart - \o Easing curve for a quartic (t^4) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinquart.png + \li \c Easing.OutInQuart + \li Easing curve for a quartic (t^4) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinquart.png \row - \o \c Easing.InQuint - \o Easing curve for a quintic (t^5) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inquint.png + \li \c Easing.InQuint + \li Easing curve for a quintic (t^5) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inquint.png \row - \o \c Easing.OutQuint - \o Easing curve for a quintic (t^5) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outquint.png + \li \c Easing.OutQuint + \li Easing curve for a quintic (t^5) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outquint.png \row - \o \c Easing.InOutQuint - \o Easing curve for a quintic (t^5) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutquint.png + \li \c Easing.InOutQuint + \li Easing curve for a quintic (t^5) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutquint.png \row - \o \c Easing.OutInQuint - \o Easing curve for a quintic (t^5) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinquint.png + \li \c Easing.OutInQuint + \li Easing curve for a quintic (t^5) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinquint.png \row - \o \c Easing.InSine - \o Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-insine.png + \li \c Easing.InSine + \li Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-insine.png \row - \o \c Easing.OutSine - \o Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outsine.png + \li \c Easing.OutSine + \li Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outsine.png \row - \o \c Easing.InOutSine - \o Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutsine.png + \li \c Easing.InOutSine + \li Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutsine.png \row - \o \c Easing.OutInSine - \o Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinsine.png + \li \c Easing.OutInSine + \li Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinsine.png \row - \o \c Easing.InExpo - \o Easing curve for an exponential (2^t) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inexpo.png + \li \c Easing.InExpo + \li Easing curve for an exponential (2^t) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inexpo.png \row - \o \c Easing.OutExpo - \o Easing curve for an exponential (2^t) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outexpo.png + \li \c Easing.OutExpo + \li Easing curve for an exponential (2^t) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outexpo.png \row - \o \c Easing.InOutExpo - \o Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutexpo.png + \li \c Easing.InOutExpo + \li Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutexpo.png \row - \o \c Easing.OutInExpo - \o Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinexpo.png + \li \c Easing.OutInExpo + \li Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinexpo.png \row - \o \c Easing.InCirc - \o Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-incirc.png + \li \c Easing.InCirc + \li Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-incirc.png \row - \o \c Easing.OutCirc - \o Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outcirc.png + \li \c Easing.OutCirc + \li Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outcirc.png \row - \o \c Easing.InOutCirc - \o Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutcirc.png + \li \c Easing.InOutCirc + \li Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutcirc.png \row - \o \c Easing.OutInCirc - \o Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outincirc.png + \li \c Easing.OutInCirc + \li Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outincirc.png \row - \o \c Easing.InElastic - \o Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity. + \li \c Easing.InElastic + \li Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity. \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. - \o \inlineimage qeasingcurve-inelastic.png + \li \inlineimage qeasingcurve-inelastic.png \row - \o \c Easing.OutElastic - \o Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity. + \li \c Easing.OutElastic + \li Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity. \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. - \o \inlineimage qeasingcurve-outelastic.png + \li \inlineimage qeasingcurve-outelastic.png \row - \o \c Easing.InOutElastic - \o Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutelastic.png + \li \c Easing.InOutElastic + \li Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutelastic.png \row - \o \c Easing.OutInElastic - \o Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinelastic.png + \li \c Easing.OutInElastic + \li Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinelastic.png \row - \o \c Easing.InBack - \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inback.png + \li \c Easing.InBack + \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inback.png \row - \o \c Easing.OutBack - \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity. - \o \inlineimage qeasingcurve-outback.png + \li \c Easing.OutBack + \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity. + \li \inlineimage qeasingcurve-outback.png \row - \o \c Easing.InOutBack - \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutback.png + \li \c Easing.InOutBack + \li Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutback.png \row - \o \c Easing.OutInBack - \o Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinback.png + \li \c Easing.OutInBack + \li Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinback.png \row - \o \c Easing.InBounce - \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity. - \o \inlineimage qeasingcurve-inbounce.png + \li \c Easing.InBounce + \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity. + \li \inlineimage qeasingcurve-inbounce.png \row - \o \c Easing.OutBounce - \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity. - \o \inlineimage qeasingcurve-outbounce.png + \li \c Easing.OutBounce + \li Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity. + \li \inlineimage qeasingcurve-outbounce.png \row - \o \c Easing.InOutBounce - \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration. - \o \inlineimage qeasingcurve-inoutbounce.png + \li \c Easing.InOutBounce + \li Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration. + \li \inlineimage qeasingcurve-inoutbounce.png \row - \o \c Easing.OutInBounce - \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration. - \o \inlineimage qeasingcurve-outinbounce.png + \li \c Easing.OutInBounce + \li Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration. + \li \inlineimage qeasingcurve-outinbounce.png \row - \o \c Easing.Bezier - \o Custom easing curve defined by the easing.bezierCurve property. - \o + \li \c Easing.Bezier + \li Custom easing curve defined by the easing.bezierCurve property. + \li \endtable \c easing.amplitude is only applicable for bounce and elastic curves (curves of type @@ -2290,8 +2290,8 @@ void QQuickPropertyAnimation::setProperties(const QString &prop) \table 80% \row - \o Value Source / Behavior - \o When an animation is used as a value source or in a Behavior, the default target and property + \li Value Source / Behavior + \li When an animation is used as a value source or in a Behavior, the default target and property name to be animated can both be inferred. \qml Rectangle { @@ -2303,8 +2303,8 @@ void QQuickPropertyAnimation::setProperties(const QString &prop) } \endqml \row - \o Transition - \o When used in a transition, a property animation is assumed to match \e all targets + \li Transition + \li When used in a transition, a property animation is assumed to match \e all targets but \e no properties. In practice, that means you need to specify at least the properties in order for the animation to do anything. \qml @@ -2328,8 +2328,8 @@ void QQuickPropertyAnimation::setProperties(const QString &prop) } \endqml \row - \o Standalone - \o When an animation is used standalone, both the target and property need to be + \li Standalone + \li When an animation is used standalone, both the target and property need to be explicitly specified. \qml Rectangle { diff --git a/src/quick/util/qquickconnections.cpp b/src/quick/util/qquickconnections.cpp index 6e176fde3d..533c7013ef 100644 --- a/src/quick/util/qquickconnections.cpp +++ b/src/quick/util/qquickconnections.cpp @@ -91,9 +91,9 @@ public: cases, such as when: \list - \i Multiple connections to the same signal are required - \i Creating connections outside the scope of the signal sender - \i Connecting to targets not defined in QML + \li Multiple connections to the same signal are required + \li Creating connections outside the scope of the signal sender + \li Connecting to targets not defined in QML \endlist When any of these are needed, the Connections element can be used instead. diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp index 438d00bd1b..55830f0cc8 100644 --- a/src/quick/util/qquickfontloader.cpp +++ b/src/quick/util/qquickfontloader.cpp @@ -295,22 +295,22 @@ void QQuickFontLoader::setName(const QString &name) This property holds the status of font loading. It can be one of: \list - \o FontLoader.Null - no font has been set - \o FontLoader.Ready - the font has been loaded - \o FontLoader.Loading - the font is currently being loaded - \o FontLoader.Error - an error occurred while loading the font + \li FontLoader.Null - no font has been set + \li FontLoader.Ready - the font has been loaded + \li FontLoader.Loading - the font is currently being loaded + \li FontLoader.Error - an error occurred while loading the font \endlist Use this status to provide an update or respond to the status change in some way. For example, you could: \list - \o Trigger a state change: + \li Trigger a state change: \qml State { name: 'loaded'; when: loader.status == FontLoader.Ready } \endqml - \o Implement an \c onStatusChanged signal handler: + \li Implement an \c onStatusChanged signal handler: \qml FontLoader { id: loader @@ -318,7 +318,7 @@ void QQuickFontLoader::setName(const QString &name) } \endqml - \o Bind to the status value: + \li Bind to the status value: \qml Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' } \endqml diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index b6a01bfe3e..adf4242cdc 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -171,14 +171,14 @@ bool QQuickPath::hasEnd() const A path can contain the following path objects: \list - \i \l PathLine - a straight line to a given position. - \i \l PathQuad - a quadratic Bezier curve to a given position with a control point. - \i \l PathCubic - a cubic Bezier curve to a given position with two control points. - \i \l PathArc - an arc to a given position with a radius. - \i \l PathSvg - a path specified as an SVG path data string. - \i \l PathCurve - a point on a Catmull-Rom curve. - \i \l PathAttribute - an attribute at a given position in the path. - \i \l PathPercent - a way to spread out items along various segments of the path. + \li \l PathLine - a straight line to a given position. + \li \l PathQuad - a quadratic Bezier curve to a given position with a control point. + \li \l PathCubic - a cubic Bezier curve to a given position with two control points. + \li \l PathArc - an arc to a given position with a radius. + \li \l PathSvg - a path specified as an SVG path data string. + \li \l PathCurve - a point on a Catmull-Rom curve. + \li \l PathAttribute - an attribute at a given position in the path. + \li \l PathPercent - a way to spread out items along various segments of the path. \endlist \snippet doc/src/snippets/qml/pathview/pathattributes.qml 2 @@ -808,8 +808,8 @@ bool QQuickCurve::hasRelativeY() \table \row - \o \image declarative-pathattribute.png - \o + \li \image declarative-pathattribute.png + \li \snippet doc/src/snippets/qml/pathview/pathattributes.qml 0 (see the PathView documentation for the specification of ContactModel.qml used for ContactModel above.) @@ -970,8 +970,8 @@ void QQuickPathLine::addToPath(QPainterPath &path, const QQuickPathData &data) The following QML produces the path shown below: \table \row - \o \image declarative-pathquad.png - \o + \li \image declarative-pathquad.png + \li \qml Path { startX: 0; startY: 0 @@ -1121,8 +1121,8 @@ void QQuickPathQuad::addToPath(QPainterPath &path, const QQuickPathData &data) The following QML produces the path shown below: \table \row - \o \image declarative-pathcubic.png - \o + \li \image declarative-pathcubic.png + \li \qml Path { startX: 20; startY: 0 @@ -1492,8 +1492,8 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa The following QML produces the path shown below: \table \row - \o \image declarative-patharc.png - \o \snippet doc/src/snippets/qml/path/basicarc.qml 0 + \li \image declarative-patharc.png + \li \snippet doc/src/snippets/qml/path/basicarc.qml 0 \endtable Note that a single PathArc cannot be used to specify a circle. Instead, you can @@ -1536,8 +1536,8 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa the shape of the arc: \table \row - \o \image declarative-arcradius.png - \o \snippet doc/src/snippets/qml/path/arcradius.qml 0 + \li \image declarative-arcradius.png + \li \snippet doc/src/snippets/qml/path/arcradius.qml 0 \endtable */ @@ -1581,8 +1581,8 @@ void QQuickPathArc::setRadiusY(qreal radius) \table \row - \o \image declarative-largearc.png - \o \snippet doc/src/snippets/qml/path/largearc.qml 0 + \li \image declarative-largearc.png + \li \snippet doc/src/snippets/qml/path/largearc.qml 0 \endtable The default value is false. @@ -1612,8 +1612,8 @@ void QQuickPathArc::setUseLargeArc(bool largeArc) by changing the value of direction. \table \row - \o \image declarative-arcdirection.png - \o \snippet doc/src/snippets/qml/path/arcdirection.qml 0 + \li \image declarative-arcdirection.png + \li \snippet doc/src/snippets/qml/path/arcdirection.qml 0 \endtable \sa useLargeArc @@ -1659,8 +1659,8 @@ void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data) The following QML produces the path shown below: \table \row - \o \image declarative-pathsvg.png - \o + \li \image declarative-pathsvg.png + \li \qml Path { startX: 50; startY: 50 @@ -1717,8 +1717,8 @@ void QQuickPathSvg::addToPath(QPainterPath &path, const QQuickPathData &) PathLine section of the path. \table \row - \o \image declarative-nopercent.png - \o + \li \image declarative-nopercent.png + \li \qml PathView { // ... @@ -1731,8 +1731,8 @@ void QQuickPathSvg::addToPath(QPainterPath &path, const QQuickPathData &) } \endqml \row - \o \image declarative-percent.png - \o + \li \image declarative-percent.png + \li \qml PathView { // ... diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp index 024728f1f5..1ad9372917 100644 --- a/src/quick/util/qquicksmoothedanimation.cpp +++ b/src/quick/util/qquicksmoothedanimation.cpp @@ -450,9 +450,9 @@ QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &a Possible values are: \list - \o SmoothedAnimation.Eased (default) - the animation will smoothly decelerate, and then reverse direction - \o SmoothedAnimation.Immediate - the animation will immediately begin accelerating in the reverse direction, beginning with a velocity of 0 - \o SmoothedAnimation.Sync - the property is immediately set to the target value + \li SmoothedAnimation.Eased (default) - the animation will smoothly decelerate, and then reverse direction + \li SmoothedAnimation.Immediate - the animation will immediately begin accelerating in the reverse direction, beginning with a velocity of 0 + \li SmoothedAnimation.Sync - the property is immediately set to the target value \endlist */ QQuickSmoothedAnimation::ReversingMode QQuickSmoothedAnimation::reversingMode() const diff --git a/src/quick/util/qquicksystempalette.cpp b/src/quick/util/qquicksystempalette.cpp index 735d18abf5..2417d573c4 100644 --- a/src/quick/util/qquicksystempalette.cpp +++ b/src/quick/util/qquicksystempalette.cpp @@ -267,9 +267,9 @@ QColor QQuickSystemPalette::highlightedText() const The color group of the palette. This can be one of: \list - \o SystemPalette.Active (default) - \o SystemPalette.Inactive - \o SystemPalette.Disabled + \li SystemPalette.Active (default) + \li SystemPalette.Inactive + \li SystemPalette.Disabled \endlist \sa QPalette::ColorGroup diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp index 3e8b36714a..61aefaf0a3 100644 --- a/src/quick/util/qquicktimeline.cpp +++ b/src/quick/util/qquicktimeline.cpp @@ -259,7 +259,7 @@ qreal QQuickTimeLinePrivate::value(const Op &op, int time, qreal base, bool *cha QQuickTimeLine is similar to QTimeLine except: \list - \i It updates QQuickTimeLineValue instances directly, rather than maintaining a single + \li It updates QQuickTimeLineValue instances directly, rather than maintaining a single current value. For example, the following animates a simple value over 200 milliseconds: @@ -274,7 +274,7 @@ qreal QQuickTimeLinePrivate::value(const Op &op, int time, qreal base, bool *cha connect to the QQuickTimeLine's updated() signal, or inherit from QQuickTimeLineValue and reimplement the QQuickTimeLineValue::setValue() method. - \i Supports multiple QQuickTimeLineValue, arbitrary start and end values and allows + \li Supports multiple QQuickTimeLineValue, arbitrary start and end values and allows animations to be strung together for more complex effects. For example, the following animation moves the x and y coordinates of @@ -294,7 +294,7 @@ qreal QQuickTimeLinePrivate::value(const Op &op, int time, qreal base, bool *cha tl.move(y, 200., 50); \endcode - \i All QQuickTimeLine instances share a single, synchronized clock. + \li All QQuickTimeLine instances share a single, synchronized clock. Actions scheduled within the same event loop tick are scheduled synchronously against each other, regardless of the wall time between the @@ -585,10 +585,10 @@ void QQuickTimeLine::sync(QQuickTimeLineValue &timeLineValue) will result in: \table - \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms - \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10 - \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0 - \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0 + \header \li \li 0ms \li 50ms \li 100ms \li 150ms \li 200ms \li 250ms \li 300ms + \row \li value1 \li 0 \li 2.5 \li 5.0 \li 7.5 \li 10 \li 10 \li 10 + \row \li value2 \li 0 \li 5.0 \li 10.0 \li 10.0 \li 10.0 \li 15.0 \li 20.0 + \row \li value2 \li 0 \li 0 \li 0 \li 0 \li 0 \li 10.0 \li 20.0 \endtable */ diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index b4b0482619..335fee0044 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -79,12 +79,12 @@ server.serveDirectory("slowFiles", TestHTTPServer::Delay); The following request urls will then result in the appropriate action: \table -\header \o URL \o Action -\row \o http://localhost:14445/disconnectTest.qml \o Disconnection -\row \o http://localhost:14445/main.qml \o main.qml returned immediately -\row \o http://localhost:14445/Button.qml \o Button.qml returned immediately -\row \o http://localhost:14445/content/WebView.qml \o content/WebView.qml returned immediately -\row \o http://localhost:14445/slowMain.qml \o slowMain.qml returned after 500ms +\header \li URL \li Action +\row \li http://localhost:14445/disconnectTest.qml \li Disconnection +\row \li http://localhost:14445/main.qml \li main.qml returned immediately +\row \li http://localhost:14445/Button.qml \li Button.qml returned immediately +\row \li http://localhost:14445/content/WebView.qml \li content/WebView.qml returned immediately +\row \li http://localhost:14445/slowMain.qml \li slowMain.qml returned after 500ms \endtable */ TestHTTPServer::TestHTTPServer(quint16 port) -- cgit v1.2.3 From c67ed6887a8ee2fac935d81630b4b77926486c9b Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Thu, 8 Mar 2012 00:12:58 +1000 Subject: More refactoring on animation controller Add a flag and helper functions for disabling user control in QAbstractAnimationJob class and make it synchronized with QDeclarativeAnimation class's disableUserControl flag. Change-Id: Ifa84ab0c78291941469c33f2cafe5f61ee718b2c Reviewed-by: Michael Brasser --- src/qml/animations/qabstractanimationjob.cpp | 36 ++++++++++-- src/qml/animations/qabstractanimationjob_p.h | 13 +++-- src/quick/util/qquickanimationcontroller.cpp | 2 + .../data/tst_coloranimation.qml | 38 +++++++++++++ .../data/tst_parallelanimation.qml | 63 +++++++++++++++++++++ .../data/tst_sequentialanimation.qml | 65 ++++++++++++++++++++++ tests/auto/quick/quick.pro | 1 + 7 files changed, 209 insertions(+), 9 deletions(-) create mode 100755 tests/auto/quick/qquickanimationcontroller/data/tst_coloranimation.qml create mode 100644 tests/auto/quick/qquickanimationcontroller/data/tst_parallelanimation.qml create mode 100644 tests/auto/quick/qquickanimationcontroller/data/tst_sequentialanimation.qml diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp index a540382847..fecd8fbc5d 100644 --- a/src/qml/animations/qabstractanimationjob.cpp +++ b/src/qml/animations/qabstractanimationjob.cpp @@ -161,6 +161,9 @@ void QQmlAnimationTimer::stopTimer() void QQmlAnimationTimer::registerAnimation(QAbstractAnimationJob *animation, bool isTopLevel) { + if (animation->userControlDisabled()) + return; + QQmlAnimationTimer *inst = instance(true); //we create the instance if needed inst->registerRunningAnimation(animation); if (isTopLevel) { @@ -206,6 +209,8 @@ void QQmlAnimationTimer::unregisterAnimation(QAbstractAnimationJob *animation) void QQmlAnimationTimer::registerRunningAnimation(QAbstractAnimationJob *animation) { + Q_ASSERT(!animation->userControlDisabled()); + if (animation->m_isGroup) return; @@ -217,6 +222,9 @@ void QQmlAnimationTimer::registerRunningAnimation(QAbstractAnimationJob *animati void QQmlAnimationTimer::unregisterRunningAnimation(QAbstractAnimationJob *animation) { + if (animation->userControlDisabled()) + return; + if (animation->m_isGroup) return; @@ -248,20 +256,21 @@ int QQmlAnimationTimer::closestPauseAnimationTimeToFinish() ///////////////////////////////////////////////////////////////////////////////////////////////////////// QAbstractAnimationJob::QAbstractAnimationJob() - : m_isPause(false) - , m_isGroup(false) - , m_loopCount(1) + : m_loopCount(1) , m_group(0) , m_direction(QAbstractAnimationJob::Forward) , m_state(QAbstractAnimationJob::Stopped) , m_totalCurrentTime(0) , m_currentTime(0) , m_currentLoop(0) - , m_hasRegisteredTimer(false) , m_uncontrolledFinishTime(-1) - , m_wasDeleted(0) , m_nextSibling(0) , m_previousSibling(0) + , m_wasDeleted(0) + , m_hasRegisteredTimer(false) + , m_isPause(false) + , m_isGroup(false) + , m_disableUserControl(false) { } @@ -482,6 +491,23 @@ void QAbstractAnimationJob::resume() setState(Running); } +void QAbstractAnimationJob::setEnableUserControl() +{ + m_disableUserControl = false; +} + +bool QAbstractAnimationJob::userControlDisabled() const +{ + return m_disableUserControl; +} + +void QAbstractAnimationJob::setDisableUserControl() +{ + m_disableUserControl = true; + start(); + pause(); +} + void QAbstractAnimationJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) { diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h index f00090cb30..e7d96ddfce 100644 --- a/src/qml/animations/qabstractanimationjob_p.h +++ b/src/qml/animations/qabstractanimationjob_p.h @@ -93,6 +93,9 @@ public: inline bool isRunning() { return m_state == Running; } inline bool isStopped() { return m_state == Stopped; } inline bool isPaused() { return m_state == Paused; } + void setDisableUserControl(); + void setEnableUserControl(); + bool userControlDisabled() const; void setCurrentTime(int msecs); @@ -128,8 +131,6 @@ protected: void directionChanged(QAbstractAnimationJob::Direction); //definition - bool m_isPause; - bool m_isGroup; int m_loopCount; QAnimationGroupJob *m_group; QAbstractAnimationJob::Direction m_direction; @@ -139,10 +140,8 @@ protected: int m_totalCurrentTime; int m_currentTime; int m_currentLoop; - bool m_hasRegisteredTimer; //records the finish time for an uncontrolled animation (used by animation groups) int m_uncontrolledFinishTime; - bool *m_wasDeleted; struct ChangeListener { ChangeListener(QAnimationJobChangeListener *l, QAbstractAnimationJob::ChangeTypes t) : listener(l), types(t) {} @@ -155,6 +154,12 @@ protected: QAbstractAnimationJob *m_nextSibling; QAbstractAnimationJob *m_previousSibling; + bool *m_wasDeleted; + bool m_hasRegisteredTimer:1; + bool m_isPause:1; + bool m_isGroup:1; + bool m_disableUserControl:1; + friend class QQmlAnimationTimer; friend class QAnimationGroupJob; }; diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp index a3e343f26d..2b5d174caa 100644 --- a/src/quick/util/qquickanimationcontroller.cpp +++ b/src/quick/util/qquickanimationcontroller.cpp @@ -174,6 +174,7 @@ void QQuickAnimationController::reload() if (oldInstance && oldInstance != d->animationInstance) delete oldInstance; d->animationInstance->setLoopCount(1); + d->animationInstance->setDisableUserControl(); d->animationInstance->start(); d->animationInstance->pause(); updateProgress(); @@ -186,6 +187,7 @@ void QQuickAnimationController::updateProgress() if (!d->animationInstance) return; + d->animationInstance->setDisableUserControl(); d->animationInstance->start(); QQmlAnimationTimer::unregisterAnimation(d->animationInstance); d->animationInstance->setCurrentTime(d->progress * d->animationInstance->duration()); diff --git a/tests/auto/quick/qquickanimationcontroller/data/tst_coloranimation.qml b/tests/auto/quick/qquickanimationcontroller/data/tst_coloranimation.qml new file mode 100755 index 0000000000..92e27b9945 --- /dev/null +++ b/tests/auto/quick/qquickanimationcontroller/data/tst_coloranimation.qml @@ -0,0 +1,38 @@ +import QtQuick 2.0 +import QtTest 1.0 + +Rectangle { + id:container + width:50 + height:50 + + Rectangle {id:rect; x:0; y:0; color:"red"; width:10; height:10} + AnimationController { + id:colorAnimationcontroller + progress:1 + animation: ColorAnimation {id:anim; target: rect; property:"color"; to:"#FFFFFF"; from:"#000000"; duration: 1000} + } + + TestCase { + name:"AnimationController" + when:windowShown + function test_colorAnimation() { + colorAnimationcontroller.progress = 0; + compare(rect.color.toString(), "#000000"); + colorAnimationcontroller.progress = 0.5; + compare(rect.color.toString(), "#7f7f7f"); + + // <=0 -> 0 + colorAnimationcontroller.progress = -1; + compare(rect.color, "#000000"); + + //>=1 -> 1 + colorAnimationcontroller.progress = 1.1; + compare(rect.color.toString(), "#ffffff"); + + //make sure the progress can be set backward + colorAnimationcontroller.progress = 0.5; + compare(rect.color, "#7f7f7f"); + } + } +} \ No newline at end of file diff --git a/tests/auto/quick/qquickanimationcontroller/data/tst_parallelanimation.qml b/tests/auto/quick/qquickanimationcontroller/data/tst_parallelanimation.qml new file mode 100644 index 0000000000..1a17a1a908 --- /dev/null +++ b/tests/auto/quick/qquickanimationcontroller/data/tst_parallelanimation.qml @@ -0,0 +1,63 @@ +import QtQuick 2.0 +import QtTest 1.0 + +Rectangle { + id:container + width:100 + height:100 + + Rectangle {id:rect; x:0; y:0; color:"red"; width:10; height:10} + AnimationController { + id:controller + progress:0 + animation: ParallelAnimation { + id:anim + NumberAnimation { target: rect; property: "x"; from:0; to: 50; duration: 1000 } + NumberAnimation { target: rect; property: "y"; from:0; to: 100; duration: 1000 } + NumberAnimation { target: rect; property: "height"; from:10; to: 50; duration: 1000 } + NumberAnimation { target: rect; property: "width"; from:10; to: 50; duration: 1000 } + ColorAnimation {target:rect; property:"color"; from:"red"; to:"blue"; duration:1000 } + } + } + + TestCase { + name:"AnimationController" + when:windowShown + function test_parallelAnimation_data() { + //FIXME:the commented lines fail on MAC OS X + return [ + {tag:"0.1",progress:0.1, x:5, y:10, color:"#e50019", width:14, height:14}, + //{tag:"0.2",progress:0.2, x:10, y:20, color:"#cb0033", width:18, height:18}, + {tag:"0.30000000000000004",progress:0.30000000000000004, x:15, y:30, color:"#b2004c", width:22, height:22}, + //{tag:"0.4",progress:0.4, x:20, y:40, color:"#980066", width:26, height:26}, + {tag:"0.5",progress:0.5, x:25, y:50, color:"#7f007f", width:30, height:30}, + {tag:"0.6",progress:0.59999999, x:29.95, y:59.9, color:"#660098", width:33.96, height:33.96}, + {tag:"0.7",progress:0.69999999, x:34.949999999999996, y:69.89999999999999, color:"#4c00b2", width:37.96, height:37.96}, + {tag:"0.7999999999999999",progress:0.7999999999999999, x:39.95, y:79.9, color:"#3300cb", width:41.96, height:41.96}, + {tag:"0.8999999999999999",progress:0.8999999999999999, x:44.95, y:89.9, color:"#1900e5", width:45.96, height:45.96}, + {tag:"0.9999999999999999",progress:0.9999999999999999, x:49.95, y:99.9, color:"#0000fe", width:49.96, height:49.96}, + {tag:"1",progress:1, x:50, y:100, color:"#0000ff", width:50, height:50}, + {tag:"0.9",progress:0.9, x:45, y:90, color:"#1900e5", width:46, height:46}, + //{tag:"0.8",progress:0.8, x:40, y:80, color:"#3200cc", width:42, height:42}, + {tag:"0.7000000000000001",progress:0.7000000000000001, x:35, y:70, color:"#4c00b2", width:38, height:38}, + //{tag:"0.6000000000000001",progress:0.6000000000000001, x:30, y:60, color:"#660098", width:34, height:34}, + {tag:"0.5000000000000001",progress:0.5000000000000001, x:25, y:50, color:"#7f007f", width:30, height:30}, + //{tag:"0.40000000000000013",progress:0.40000000000000013, x:20, y:40, color:"#980066", width:26, height:26}, + {tag:"0.30000000000000016",progress:0.30000000000000016, x:15, y:30, color:"#b2004c", width:22, height:22}, + //{tag:"0.20000000000000015",progress:0.19999999999999999, x:10, y:20, color:"#cb0033", width:18, height:18}, + {tag:"0.10000000000000014",progress:0.10000000000000014, x:5, y:10, color:"#e50019", width:14, height:14}, + {tag:"1.3877787807814457e-16",progress:1.3877787807814457e-16, x:0, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0",progress:0, x:0, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.1",progress:0.1, x:5, y:10, color:"#e50019", width:14, height:14} + ]; + } + function test_parallelAnimation(row) { + controller.progress = row.progress; + compare(rect.x, row.x); + compare(rect.y, row.y); + compare(rect.width, row.width); + compare(rect.height, row.height); + compare(rect.color.toString(), row.color); + } + } +} diff --git a/tests/auto/quick/qquickanimationcontroller/data/tst_sequentialanimation.qml b/tests/auto/quick/qquickanimationcontroller/data/tst_sequentialanimation.qml new file mode 100644 index 0000000000..59671f5145 --- /dev/null +++ b/tests/auto/quick/qquickanimationcontroller/data/tst_sequentialanimation.qml @@ -0,0 +1,65 @@ +import QtQuick 2.0 +import QtTest 1.0 + +Rectangle { + id:container + width:100 + height:100 + + Rectangle {id:rect; x:0; y:0; color:"red"; width:10; height:10} + AnimationController { + id:controller + progress:0 + animation: SequentialAnimation { + id:anim + NumberAnimation { target: rect; property: "x"; from:0; to: 50; duration: 1000 } + NumberAnimation { target: rect; property: "y"; from:0; to: 100; duration: 1000 } + NumberAnimation { target: rect; property: "height"; from:10; to: 50; duration: 1000 } + NumberAnimation { target: rect; property: "width"; from:10; to: 50; duration: 1000 } + ColorAnimation {target:rect; property:"color"; from:"red"; to:"blue"; duration:1000 } + } + } + + + TestCase { + name:"AnimationController" + when:windowShown + function test_sequentialAnimation_data() { + return [ + {tag:"0.1",progress:0.1, x:25, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.2",progress:0.2, x:50, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.30000000000000004",progress:0.30000000000000004, x:50, y:50, color:"#ff0000", width:10, height:10}, + {tag:"0.4",progress:0.4, x:50, y:100, color:"#ff0000", width:10, height:10}, + {tag:"0.5",progress:0.5, x:50, y:100, color:"#ff0000", width:10, height:30}, + {tag:"0.6",progress:0.5999999999999, x:50, y:100, color:"#ff0000", width:10, height:49.96}, + {tag:"0.7",progress:0.6999999999999, x:50, y:100, color:"#ff0000", width:29.96, height:50}, + {tag:"0.7999999999999999",progress:0.7999999999999999, x:50, y:100, color:"#ff0000", width:49.96, height:50}, + {tag:"0.8999999999999999",progress:0.8999999999999999, x:50, y:100, color:"#7f007f", width:50, height:50}, + {tag:"0.9999999999999999",progress:0.9999999999999999, x:50, y:100, color:"#0000fe", width:50, height:50}, + {tag:"1",progress:1, x:50, y:100, color:"#0000ff", width:50, height:50}, + {tag:"0.9",progress:0.9, x:50, y:100, color:"#7f007f", width:50, height:50}, + {tag:"0.8",progress:0.8, x:50, y:100, color:"#ff0000", width:50, height:50}, + {tag:"0.7000000000000001",progress:0.7000000000000001, x:50, y:100, color:"#ff0000", width:30, height:50}, + {tag:"0.6000000000000001",progress:0.6000000000000001, x:50, y:100, color:"#ff0000", width:10, height:50}, + {tag:"0.5000000000000001",progress:0.5000000000000001, x:50, y:100, color:"#ff0000", width:10, height:30}, + {tag:"0.40000000000000013",progress:0.40000000000000013, x:50, y:100, color:"#ff0000", width:10, height:10}, + {tag:"0.30000000000000016",progress:0.30000000000000016, x:50, y:50, color:"#ff0000", width:10, height:10}, + {tag:"0.20000000000000015",progress:0.20000000000000015, x:50, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.10000000000000014",progress:0.10000000000000014, x:25, y:0, color:"#ff0000", width:10, height:10}, + {tag:"1.3877787807814457e-16",progress:1.3877787807814457e-16, x:0, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0",progress:0, x:0, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.1",progress:0.1, x:25, y:0, color:"#ff0000", width:10, height:10}, + {tag:"0.2",progress:0.2, x:50, y:0, color:"#ff0000", width:10, height:10} + + ]; + } + function test_sequentialAnimation(row) { + controller.progress = row.progress; + compare(rect.x, row.x); + compare(rect.y, row.y); + compare(rect.width, row.width); + compare(rect.height, row.height); + compare(rect.color.toString(), row.color); + } + } +} diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 4065dbf508..c8014be820 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -18,6 +18,7 @@ PRIVATETESTS += \ qquickpath \ qquicksmoothedanimation \ qquickspringanimation \ + qquickanimationcontroller \ qquickstyledtext \ qquickstates \ qquicksystempalette \ -- cgit v1.2.3 From 89d6599de9092ac1f5e24981e642d87d57f593b5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 14 Mar 2012 09:50:31 +1000 Subject: Reuse QQuickView in GridView table driven tests Makes the tests run faster since we're not waiting for a window to appear all the time. Change-Id: Id2442cf32055084088c19865499055c7282bcae0 Reviewed-by: Bea Lam --- .../quick/qquickgridview/tst_qquickgridview.cpp | 128 ++++++++++++++------- 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 7d004915a6..928151d59e 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -64,6 +64,8 @@ Q_DECLARE_METATYPE(QQuickGridView::Flow) using namespace QQuickViewTestUtil; using namespace QQuickVisualTestUtil; +#define SHARE_VIEWS + class tst_QQuickGridView : public QQmlDataTest { Q_OBJECT @@ -71,6 +73,7 @@ public: tst_QQuickGridView(); private slots: + void init(); void items(); void changed(); void inserted(); @@ -149,10 +152,53 @@ private: void matchIndexLists(const QVariantList &indexLists, const QList &expectedIndexes); void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList &expectedIndexes); void matchItemLists(const QVariantList &itemLists, const QList &expectedItems); + +#ifdef SHARE_VIEWS + QQuickView *getView() { + if (m_view) { + if (QString(QTest::currentTestFunction()) != testForView) { + delete m_view; + m_view = 0; + } else { + m_view->setSource(QUrl()); + return m_view; + } + } + + testForView = QTest::currentTestFunction(); + m_view = createView(); + return m_view; + } + void releaseView(QQuickView *view) { + Q_ASSERT(view == m_view); + m_view->setSource(QUrl()); + } +#else + QQuickView *getView() { + return createView(); + } + void releaseView(QQuickView *view) { + delete view; + } +#endif + + QQuickView *m_view; + QString testForView; }; -tst_QQuickGridView::tst_QQuickGridView() +tst_QQuickGridView::tst_QQuickGridView() : m_view(0) +{ +} + +void tst_QQuickGridView::init() { +#ifdef SHARE_VIEWS + if (m_view && QString(QTest::currentTestFunction()) != testForView) { + testForView = QString(); + delete m_view; + m_view = 0; + } +#endif } void tst_QQuickGridView::items() @@ -334,7 +380,7 @@ void tst_QQuickGridView::inserted_more() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("testRightToLeft", QVariant(false)); @@ -393,7 +439,7 @@ void tst_QQuickGridView::inserted_more() QCOMPARE(number->text(), model.number(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::inserted_more_data() @@ -502,7 +548,7 @@ void tst_QQuickGridView::insertBeforeVisible() QFETCH(int, cacheBuffer); QQuickText *name; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QaimModel model; for (int i = 0; i < 30; i++) @@ -560,7 +606,7 @@ void tst_QQuickGridView::insertBeforeVisible() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::insertBeforeVisible_data() @@ -741,7 +787,7 @@ void tst_QQuickGridView::removed_more() QQuickText *name; QQuickText *number; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QaimModel model; for (int i = 0; i < 30; i++) @@ -798,7 +844,7 @@ void tst_QQuickGridView::removed_more() QTRY_COMPARE(number->text(), model.number(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::removed_more_data() @@ -934,7 +980,7 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible() QFETCH(bool, doAdd); QFETCH(qreal, newTopContentY); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->show(); QaimModel model; @@ -1000,7 +1046,7 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible() QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::addOrRemoveBeforeVisible_data() @@ -1061,7 +1107,7 @@ void tst_QQuickGridView::moved() QQuickText *name; QQuickText *number; - QScopedPointer canvas(createView()); + QQuickView *canvas = getView(); QaimModel model; for (int i = 0; i < 30; i++) @@ -1116,6 +1162,8 @@ void tst_QQuickGridView::moved() if (item == currentItem) QTRY_COMPARE(gridview->currentIndex(), i); } + + releaseView(canvas); } void tst_QQuickGridView::moved_data() @@ -1279,7 +1327,7 @@ void tst_QQuickGridView::multipleChanges() QFETCH(int, newCount); QFETCH(int, newCurrentIndex); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QaimModel model; for (int i = 0; i < startCount; i++) @@ -1347,7 +1395,7 @@ void tst_QQuickGridView::multipleChanges() QTRY_COMPARE(number->text(), model.number(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::multipleChanges_data() @@ -2778,7 +2826,7 @@ void tst_QQuickGridView::footer() QFETCH(QPointF, firstDelegatePos); QFETCH(QPointF, resizeContentPos); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->show(); QaimModel model; @@ -2876,7 +2924,7 @@ void tst_QQuickGridView::footer() footer->setWidth(40); QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos); - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::footer_data() @@ -2948,7 +2996,7 @@ void tst_QQuickGridView::header() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("initialViewWidth", 240); canvas->rootContext()->setContextProperty("initialViewHeight", 320); @@ -3016,12 +3064,12 @@ void tst_QQuickGridView::header() header->setWidth(40); QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos); - delete canvas; + releaseView(canvas); // QTBUG-21207 header should become visible if view resizes from initial empty size - canvas = createView(); + canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("initialViewWidth", 240); canvas->rootContext()->setContextProperty("initialViewHeight", 320); @@ -3040,7 +3088,7 @@ void tst_QQuickGridView::header() QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos); QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos); - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::header_data() @@ -3244,7 +3292,7 @@ void tst_QQuickGridView::indexAt_itemAt() QFETCH(qreal, y); QFETCH(int, index); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QaimModel model; model.addItem("Fred", "12345"); @@ -3279,7 +3327,7 @@ void tst_QQuickGridView::indexAt_itemAt() QCOMPARE(gridview->indexAt(x, y), index); QVERIFY(gridview->itemAt(x, y) == item); - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::onAdd() @@ -3290,7 +3338,7 @@ void tst_QQuickGridView::onAdd() const int delegateWidth = 50; const int delegateHeight = 100; QaimModel model; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit // these initial items should not trigger GridView.onAdd @@ -3321,7 +3369,7 @@ void tst_QQuickGridView::onAdd() for (int i=0; irootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("delegateWidth", delegateWidth); @@ -3366,7 +3414,7 @@ void tst_QQuickGridView::onRemove() QTRY_COMPARE(model.count(), qobject_cast(canvas->rootObject())->count()); QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::onRemove_data() @@ -3602,7 +3650,7 @@ void tst_QQuickGridView::snapToRow() QFETCH(qreal, endExtent); QFETCH(qreal, startExtent); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("snapToRow.qml")); canvas->show(); @@ -3653,7 +3701,7 @@ void tst_QQuickGridView::snapToRow() else QCOMPARE(gridview->contentX(), startExtent); - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::snapOneRow_data() @@ -3697,7 +3745,7 @@ void tst_QQuickGridView::snapOneRow() QFETCH(qreal, endExtent); QFETCH(qreal, startExtent); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("snapOneRow.qml")); canvas->show(); @@ -3765,7 +3813,7 @@ void tst_QQuickGridView::snapOneRow() QCOMPARE(currentIndexSpy.count(), 6); } - delete canvas; + releaseView(canvas); } @@ -3846,7 +3894,7 @@ void tst_QQuickGridView::populateTransitions() model.addItem("item" + QString::number(i), ""); } - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); canvas->rootContext()->setContextProperty("testModel", &model); canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition); canvas->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate); @@ -3944,7 +3992,7 @@ void tst_QQuickGridView::populateTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::populateTransitions_data() @@ -3984,7 +4032,7 @@ void tst_QQuickGridView::addTransitions() QaimModel model_targetItems_transitionFrom; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom); @@ -4080,7 +4128,7 @@ void tst_QQuickGridView::addTransitions() QCOMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::addTransitions_data() @@ -4189,7 +4237,7 @@ void tst_QQuickGridView::moveTransitions() QaimModel model_targetItems_transitionVia; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia); @@ -4277,7 +4325,7 @@ void tst_QQuickGridView::moveTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::moveTransitions_data() @@ -4395,7 +4443,7 @@ void tst_QQuickGridView::removeTransitions() QaimModel model_targetItems_transitionTo; QaimModel model_displacedItems_transitionVia; - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo); @@ -4492,7 +4540,7 @@ void tst_QQuickGridView::removeTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::removeTransitions_data() @@ -4599,7 +4647,7 @@ void tst_QQuickGridView::displacedTransitions() QPointF moveDisplaced_transitionVia(50, -100); QPointF removeDisplaced_transitionVia(150, 100); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("model_displaced_transitionVia", &model_displaced_transitionVia); @@ -4709,7 +4757,7 @@ void tst_QQuickGridView::displacedTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::displacedTransitions_data() @@ -4822,7 +4870,7 @@ void tst_QQuickGridView::multipleTransitions() for (int i = 0; i < initialCount; i++) model.addItem("Original item" + QString::number(i), ""); - QQuickView *canvas = createView(); + QQuickView *canvas = getView(); QQmlContext *ctxt = canvas->rootContext(); ctxt->setContextProperty("testModel", &model); ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom); @@ -4924,7 +4972,7 @@ void tst_QQuickGridView::multipleTransitions() QTRY_COMPARE(name->text(), model.name(i)); } - delete canvas; + releaseView(canvas); } void tst_QQuickGridView::multipleTransitions_data() -- cgit v1.2.3 From 665f860d9aaccd222c7fa8e309f087be35768022 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 8 Mar 2012 14:41:40 +1000 Subject: Support module api objects in v4. Change-Id: I72911a2c8e0a8613e53861da7b38312e51bf57da Reviewed-by: Roberto Raggi --- src/qml/qml/v4/qv4bindings.cpp | 23 ++++++++++ src/qml/qml/v4/qv4compiler.cpp | 16 +++++++ src/qml/qml/v4/qv4instruction.cpp | 3 ++ src/qml/qml/v4/qv4instruction_p.h | 1 + src/qml/qml/v4/qv4ir.cpp | 13 ++++++ src/qml/qml/v4/qv4ir_p.h | 2 + src/qml/qml/v4/qv4irbuilder.cpp | 51 ++++++++++++++++++++++ .../data/moduleapi/qobjectModuleApiWriting.qml | 8 +++- tests/auto/qml/qqmlecmascript/testtypes.cpp | 1 + tests/auto/qml/qqmlecmascript/testtypes.h | 8 +++- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 12 ++--- 11 files changed, 129 insertions(+), 9 deletions(-) diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 93c7820ca2..89e831ca3f 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -820,6 +820,29 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, registers[instr->load.reg].setQObject(context->contextObject); QML_V4_END_INSTR(LoadRoot, load) + QML_V4_BEGIN_INSTR(LoadModuleObject, load) + { + Register ® = registers[instr->load.reg]; + + const QString *name = reg.getstringptr(); + QQmlTypeNameCache::Result r = context->imports->query(*name); + reg.cleanupString(); + + if (r.isValid() && r.importNamespace) { + QQmlMetaType::ModuleApiInstance *moduleApi = context->imports->moduleApi(r.importNamespace); + if (moduleApi) { + if (moduleApi->qobjectCallback) { + moduleApi->qobjectApi = moduleApi->qobjectCallback(context->engine, context->engine); + moduleApi->qobjectCallback = 0; + moduleApi->scriptCallback = 0; + } + if (moduleApi->qobjectApi) + reg.setQObject(moduleApi->qobjectApi); + } + } + } + QML_V4_END_INSTR(LoadModuleObject, load) + QML_V4_BEGIN_INSTR(LoadAttached, attached) { const Register &input = registers[instr->attached.reg]; diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index 620d260053..b22708d7db 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -318,6 +318,22 @@ void QV4CompilerPrivate::visitName(IR::Name *e) gen(attached); } break; + case IR::Name::ModuleObject: { + /* + Existing module object lookup methods include: + 1. string -> module object (search via importCache->query(name)) + 2. QQmlMetaType::ModuleApi -> module object (via QQmlEnginePrivate::moduleApiInstance() cache) + We currently use 1, which is not ideal for performance + */ + _subscribeName << *e->id; + + registerLiteralString(currentReg, e->id); + + Instr::LoadModuleObject module; + module.reg = currentReg; + gen(module); + } break; + case IR::Name::Property: { _subscribeName << *e->id; diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp index a392c9392c..e26014765d 100644 --- a/src/qml/qml/v4/qv4instruction.cpp +++ b/src/qml/qml/v4/qv4instruction.cpp @@ -114,6 +114,9 @@ void Bytecode::dump(const V4Instr *i, int address) const case V4Instr::LoadRoot: INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")"; break; + case V4Instr::LoadModuleObject: + INSTR_DUMP << "\t" << "LoadModuleObject" << "\t\t" << ") -> Output_Reg(" << i->load.reg << ")"; + break; case V4Instr::LoadAttached: INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")"; break; diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h index 9727c23959..d33051840d 100644 --- a/src/qml/qml/v4/qv4instruction_p.h +++ b/src/qml/qml/v4/qv4instruction_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE F(LoadId, load) \ F(LoadScope, load) \ F(LoadRoot, load) \ + F(LoadModuleObject, load) \ F(LoadAttached, attached) \ F(UnaryNot, unaryop) \ F(UnaryMinusReal, unaryop) \ diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp index 54679c3d8c..34245f5bf4 100644 --- a/src/qml/qml/v4/qv4ir.cpp +++ b/src/qml/qml/v4/qv4ir.cpp @@ -543,6 +543,17 @@ Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Nam return name; } +Name *BasicBlock::MODULE_OBJECT(const QString &id, const QMetaObject *meta, Name::Storage storage, + quint32 line, quint32 column) +{ + Name *name = function->pool->New(); + name->init(/*base = */ 0, IR::ObjectType, + function->newString(id), + Name::ModuleObject, line, column); + name->meta = meta; + name->storage = storage; + return name; +} Expr *BasicBlock::UNOP(AluOp op, Expr *expr) { @@ -675,6 +686,8 @@ static const char *symbolname(Name::Symbol s) return "IdObject"; case Name::AttachType: return "AttachType"; + case Name::ModuleObject: + return "ModuleObject"; case Name::Object: return "Object"; case Name::Property: diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h index 79f50cd6c9..4e9f9faacd 100644 --- a/src/qml/qml/v4/qv4ir_p.h +++ b/src/qml/qml/v4/qv4ir_p.h @@ -252,6 +252,7 @@ struct Name: Expr { Unbound, IdObject, // This is a load of a id object. Storage will always be IdStorage AttachType, // This is a load of an attached object + ModuleObject, // This is a load of a module object Object, // XXX what is this for? Property, // This is a load of a regular property Slot // XXX what is this for? @@ -538,6 +539,7 @@ struct BasicBlock { Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column); Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column); Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint32 line, quint32 column); + Name *MODULE_OBJECT(const QString &id, const QMetaObject *meta, Name::Storage storage, quint32 line, quint32 column); Expr *UNOP(AluOp op, Expr *expr); Expr *BINOP(AluOp op, Expr *left, Expr *right); diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 06f4024423..8f7422454a 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -428,6 +428,17 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) if (r.isValid()) { if (r.type) { _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); + } else if (r.importNamespace) { + QQmlMetaType::ModuleApiInstance *moduleApi = m_expression->importCache->moduleApi(r.importNamespace); + if (moduleApi) { + if (moduleApi->qobjectCallback) { + moduleApi->qobjectApi = moduleApi->qobjectCallback(QQmlEnginePrivate::get(m_engine), QQmlEnginePrivate::get(m_engine)); + moduleApi->qobjectCallback = 0; + moduleApi->scriptCallback = 0; + } + if (moduleApi->qobjectApi) + _expr.code = _block->MODULE_OBJECT(name, moduleApi->qobjectApi->metaObject(), IR::Name::MemberStorage, line, column); + } } // We don't support anything else } else { @@ -603,6 +614,46 @@ bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast) } break; + case IR::Name::ModuleObject: { + if (name.at(0).isUpper()) { + QByteArray utf8Name = name.toUtf8(); + const char *enumName = utf8Name.constData(); + + const QMetaObject *meta = baseName->meta; + bool found = false; + for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) { + QMetaEnum e = meta->enumerator(ii); + for (int jj = 0; !found && jj < e.keyCount(); ++jj) { + if (0 == strcmp(e.key(jj), enumName)) { + found = true; + _expr.code = _block->CONST(IR::IntType, e.value(jj)); + } + } + } + if (!found && qmlVerboseCompiler()) + qWarning() << "*** unresolved enum:" + << (*baseName->id + QLatin1String(".") + ast->name.toString()); + } else { + QQmlPropertyCache *cache = m_engine->cache(baseName->meta); + if (!cache) return false; + QQmlPropertyData *data = cache->property(name); + + if (!data || data->isFunction()) + return false; // Don't support methods (or non-existing properties ;) + + if (!data->isFinal()) { + if (qmlVerboseCompiler()) + qWarning() << "*** non-final attached property:" + << (*baseName->id + QLatin1String(".") + ast->name.toString()); + return false; // We don't know enough about this property + } + + IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta); + _expr.code = _block->SYMBOL(baseName, irType, name, baseName->meta, data, line, column); + } + } + break; + case IR::Name::IdObject: { const QQmlScript::Object *idObject = baseName->idObject; QQmlPropertyCache *cache = diff --git a/tests/auto/qml/qqmlecmascript/data/moduleapi/qobjectModuleApiWriting.qml b/tests/auto/qml/qqmlecmascript/data/moduleapi/qobjectModuleApiWriting.qml index be647ca57f..e4a68d14ea 100644 --- a/tests/auto/qml/qqmlecmascript/data/moduleapi/qobjectModuleApiWriting.qml +++ b/tests/auto/qml/qqmlecmascript/data/moduleapi/qobjectModuleApiWriting.qml @@ -6,6 +6,7 @@ QtObject { property int secondProperty: 2 property int readOnlyProperty: QtTest.qobjectTestProperty property int writableProperty: QtTest.qobjectTestWritableProperty + property int writableFinalProperty: QtTest.qobjectTestWritableFinalProperty onFirstPropertyChanged: { // In this case, we want to attempt to set the module API property. @@ -16,11 +17,14 @@ QtObject { } onSecondPropertyChanged: { - // In this case, we want to attempt to set the module API property. - // This should succeed, as the module API property is writable. + // In this case, we want to attempt to set the module API properties. + // This should succeed, as the module API properties are writable. if (secondProperty != QtTest.qobjectTestWritableProperty) { QtTest.qobjectTestWritableProperty = secondProperty; // should succeed. } + if (secondProperty != QtTest.qobjectTestWritableFinalProperty) { + QtTest.qobjectTestWritableFinalProperty = secondProperty; // should succeed. + } } } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 78119cb776..64e91fbc95 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -140,6 +140,7 @@ static QObject *qobject_api(QQmlEngine *engine, QJSEngine *scriptEngine) testQObjectApi *o = new testQObjectApi(); o->setQObjectTestProperty(20); o->setQObjectTestWritableProperty(50); + o->setQObjectTestWritableFinalProperty(10); return o; } diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 1d68e8ae13..65b84d66cb 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -978,10 +978,11 @@ class testQObjectApi : public QObject Q_ENUMS(MyEnum) Q_PROPERTY (int qobjectTestProperty READ qobjectTestProperty NOTIFY qobjectTestPropertyChanged) Q_PROPERTY (int qobjectTestWritableProperty READ qobjectTestWritableProperty WRITE setQObjectTestWritableProperty NOTIFY qobjectTestWritablePropertyChanged) + Q_PROPERTY (int qobjectTestWritableFinalProperty READ qobjectTestWritableFinalProperty WRITE setQObjectTestWritableFinalProperty NOTIFY qobjectTestWritableFinalPropertyChanged FINAL) public: testQObjectApi(QObject* parent = 0) - : QObject(parent), m_testProperty(0), m_testWritableProperty(0), m_methodCallCount(0) + : QObject(parent), m_testProperty(0), m_testWritableProperty(0), m_testWritableFinalProperty(0), m_methodCallCount(0) { } @@ -997,13 +998,18 @@ public: int qobjectTestWritableProperty() const { return m_testWritableProperty; } void setQObjectTestWritableProperty(int tp) { m_testWritableProperty = tp; emit qobjectTestWritablePropertyChanged(tp); } + int qobjectTestWritableFinalProperty() const { return m_testWritableFinalProperty; } + void setQObjectTestWritableFinalProperty(int tp) { m_testWritableFinalProperty = tp; emit qobjectTestWritableFinalPropertyChanged(); } + signals: void qobjectTestPropertyChanged(int testProperty); void qobjectTestWritablePropertyChanged(int testWritableProperty); + void qobjectTestWritableFinalPropertyChanged(); private: int m_testProperty; int m_testWritableProperty; + int m_testWritableFinalProperty; int m_methodCallCount; }; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 5770dc4e03..0631df1759 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3089,13 +3089,13 @@ void tst_qqmlecmascript::moduleApi_data() QTest::newRow("qobject, writing + readonly constraints") << testFileUrl("moduleapi/qobjectModuleApiWriting.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\""))) - << (QStringList() << "readOnlyProperty" << "writableProperty") - << (QVariantList() << 20 << 50) - << (QStringList() << "firstProperty" << "writableProperty") + << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\""))) + << (QStringList() << "readOnlyProperty" << "writableProperty" << "writableFinalProperty") + << (QVariantList() << 20 << 50 << 10) + << (QStringList() << "firstProperty" << "secondProperty") << (QVariantList() << 30 << 30) - << (QStringList() << "readOnlyProperty" << "writableProperty") - << (QVariantList() << 20 << 30); + << (QStringList() << "readOnlyProperty" << "writableProperty" << "writableFinalProperty") + << (QVariantList() << 20 << 30 << 30); QTest::newRow("script, writing + readonly constraints") << testFileUrl("moduleapi/scriptModuleApiWriting.qml") -- cgit v1.2.3 From 6b8c356401259675204126897a563cf020bd68f4 Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Wed, 29 Feb 2012 11:48:06 +1000 Subject: Refactor canvas examples by following the new example guidelines. Change-Id: I1cc749ad11b8439239ba739f40e99b78af7351ab Reviewed-by: Yunqiao Yin --- examples/demos/stockchart/README | 5 + .../stockchart/com/nokia/StockChartExample/qmldir | 1 + examples/demos/stockchart/model.cpp | 255 ++++++++ examples/demos/stockchart/model.h | 166 +++++ examples/demos/stockchart/plugin.cpp | 60 ++ examples/demos/stockchart/stock.qml | 726 +++++++++++++++++++++ examples/demos/stockchart/stockchart.pro | 20 + examples/demos/stockchart/stockchart.qmlproject | 16 + examples/demos/twitterfriends/TwitterUser.qml | 294 +++++++++ examples/demos/twitterfriends/cache.js | 42 ++ examples/demos/twitterfriends/friends.qml | 140 ++++ .../demos/twitterfriends/twitterfriends.qmlproject | 16 + examples/quick/canvas/bezierCurve/bezierCurve.qml | 24 +- examples/quick/canvas/canvas.pro | 9 + examples/quick/canvas/canvas.qml | 85 +++ examples/quick/canvas/clip/clip.qml | 24 +- examples/quick/canvas/contents/Button.qml | 2 +- examples/quick/canvas/main.cpp | 41 ++ .../canvas/quadraticCurveTo/quadraticCurveTo.qml | 24 +- examples/quick/canvas/roundedrect/roundedrect.qml | 24 +- examples/quick/canvas/smile/smile.qml | 24 +- examples/quick/canvas/squircle/squircle.qml | 24 +- examples/quick/canvas/stockchart/README | 5 - .../stockchart/com/nokia/StockChartExample/qmldir | 1 - examples/quick/canvas/stockchart/model.cpp | 255 -------- examples/quick/canvas/stockchart/model.h | 166 ----- examples/quick/canvas/stockchart/plugin.cpp | 60 -- examples/quick/canvas/stockchart/stock.qml | 726 --------------------- examples/quick/canvas/stockchart/stockchart.pro | 20 - examples/quick/canvas/tiger/tiger.qml | 22 +- .../quick/canvas/twitterfriends/TwitterUser.qml | 294 --------- examples/quick/canvas/twitterfriends/cache.js | 42 -- examples/quick/canvas/twitterfriends/twitter.qml | 141 ---- 33 files changed, 1960 insertions(+), 1794 deletions(-) create mode 100644 examples/demos/stockchart/README create mode 100644 examples/demos/stockchart/com/nokia/StockChartExample/qmldir create mode 100644 examples/demos/stockchart/model.cpp create mode 100644 examples/demos/stockchart/model.h create mode 100644 examples/demos/stockchart/plugin.cpp create mode 100644 examples/demos/stockchart/stock.qml create mode 100644 examples/demos/stockchart/stockchart.pro create mode 100644 examples/demos/stockchart/stockchart.qmlproject create mode 100644 examples/demos/twitterfriends/TwitterUser.qml create mode 100644 examples/demos/twitterfriends/cache.js create mode 100644 examples/demos/twitterfriends/friends.qml create mode 100644 examples/demos/twitterfriends/twitterfriends.qmlproject create mode 100644 examples/quick/canvas/canvas.pro create mode 100644 examples/quick/canvas/canvas.qml create mode 100644 examples/quick/canvas/main.cpp delete mode 100644 examples/quick/canvas/stockchart/README delete mode 100644 examples/quick/canvas/stockchart/com/nokia/StockChartExample/qmldir delete mode 100644 examples/quick/canvas/stockchart/model.cpp delete mode 100644 examples/quick/canvas/stockchart/model.h delete mode 100644 examples/quick/canvas/stockchart/plugin.cpp delete mode 100644 examples/quick/canvas/stockchart/stock.qml delete mode 100644 examples/quick/canvas/stockchart/stockchart.pro delete mode 100644 examples/quick/canvas/twitterfriends/TwitterUser.qml delete mode 100644 examples/quick/canvas/twitterfriends/cache.js delete mode 100644 examples/quick/canvas/twitterfriends/twitter.qml diff --git a/examples/demos/stockchart/README b/examples/demos/stockchart/README new file mode 100644 index 0000000000..2652866ed6 --- /dev/null +++ b/examples/demos/stockchart/README @@ -0,0 +1,5 @@ +To run: + + make install + QML_IMPORT_PATH=$PWD qmlscene stock.qml + diff --git a/examples/demos/stockchart/com/nokia/StockChartExample/qmldir b/examples/demos/stockchart/com/nokia/StockChartExample/qmldir new file mode 100644 index 0000000000..4c60e556d4 --- /dev/null +++ b/examples/demos/stockchart/com/nokia/StockChartExample/qmldir @@ -0,0 +1 @@ +plugin qmlstockchartexampleplugin diff --git a/examples/demos/stockchart/model.cpp b/examples/demos/stockchart/model.cpp new file mode 100644 index 0000000000..42eb2d592f --- /dev/null +++ b/examples/demos/stockchart/model.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "model.h" + +#include +#include +#include +#include +#include + +#include +#include + +StockModel::StockModel(QObject *parent) + : QAbstractListModel(parent) + , _startDate(QDate(1995, 4, 25)) + , _endDate(QDate::currentDate()) + , _dataCycle(StockModel::Daily) + , _manager(0) + , _updating(false) +{ + QHash roles; + roles[StockModel::DateRole] = "date"; + roles[StockModel::SectionRole] = "year"; + roles[StockModel::OpenPriceRole] = "openPrice"; + roles[StockModel::ClosePriceRole] = "closePrice"; + roles[StockModel::HighPriceRole] = "highPrice"; + roles[StockModel::LowPriceRole] = "lowPrice"; + roles[StockModel::VolumeRole] = "volume"; + roles[StockModel::AdjustedPriceRole] = "adjustedPrice"; + setRoleNames(roles); + + connect(this, SIGNAL(stockNameChanged()), SLOT(requestData())); + connect(this, SIGNAL(startDateChanged()), SLOT(requestData())); + connect(this, SIGNAL(endDateChanged()), SLOT(requestData())); + connect(this, SIGNAL(dataCycleChanged()), SLOT(requestData())); + + _manager = new QNetworkAccessManager(this); + connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(update(QNetworkReply*))); + +} + +int StockModel::rowCount(const QModelIndex & parent) const { + Q_UNUSED(parent); + return _prices.count(); +} + +StockPrice* StockModel::stockPriceAtIndex(int idx) const +{ + if (idx >=0 && idx < _prices.size()) { + return _prices[idx]; + } + return 0; +} + + +void StockModel::requestData() +{ + if (!_updating) { + _updating = true; + QMetaObject::invokeMethod(this, "doRequest", Qt::QueuedConnection); + } +} + +void StockModel::doRequest() +{ + /* + Fetch stock data from yahoo finance: + url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv + s:stock name/id, a:start day, b:start month, c:start year default: 25 April 1995, oldest c= 1962 + d:end day, e:end month, f:end year, default:today (data only available 3 days before today) + g:data cycle(d daily, w weekly, m monthly, v Dividend) + */ + if (_manager && !_stockName.isEmpty() && _endDate > _startDate) { + QString query("http://ichart.finance.yahoo.com/table.csv?s=%1&a=%2&b=%3&c=%4&d=%5&e=%6&f=%7&g=%8&ignore=.csv"); + query = query.arg(_stockName) + .arg(_startDate.day()).arg(_startDate.month()).arg(_startDate.year()) + .arg(_endDate.day()).arg(_endDate.month()).arg(_endDate.year()) + .arg(dataCycleString()); + + qDebug() << "request stock data:" << query; + QNetworkReply* reply = _manager->get(QNetworkRequest(QUrl(query))); + connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(downloadProgress(qint64,qint64))); + } +} + +void StockModel::update(QNetworkReply *reply) +{ + _updating = false; + + if (reply) { + if (reply->error() == QNetworkReply::NoError) { + beginResetModel(); + + foreach (StockPrice* p, _prices) { + p->deleteLater(); + } + + _prices.clear(); + + while (!reply->atEnd()) { + QString line = reply->readLine(); + QStringList fields = line.split(','); + + //data format:Date,Open,High,Low,Close,Volume,Adjusted close price + //example: 2011-06-24,6.03,6.04,5.88,5.88,20465200,5.88 + if (fields.size() == 7) { + StockPrice* price = new StockPrice(this); + price->setDate(QDate::fromString(fields[0], Qt::ISODate)); + price->setOpenPrice(fields[1].toFloat()); + price->setHighPrice(fields[2].toFloat()); + price->setLowPrice(fields[3].toFloat()); + price->setClosePrice(fields[4].toFloat()); + price->setVolume(fields[5].toInt()); + price->setAdjustedPrice(fields[6].toFloat()); + _prices.prepend(price); + } + } + qDebug() << "get stock data successfully, total:" << _prices.count() << "records."; + } else { + qDebug() << "get stock data failed:" << reply->errorString(); + } + reply->deleteLater(); + endResetModel(); + emit dataChanged(QModelIndex(), QModelIndex()); + } +} + +QVariant StockModel::data(const QModelIndex & index, int role) const { + if (index.row() < 0 || index.row() > _prices.count()) + return QVariant(); + + const StockPrice* price = _prices[index.row()]; + if (role == StockModel::DateRole) + return price->date(); + else if (role == StockModel::OpenPriceRole) + return price->openPrice(); + else if (role == StockModel::ClosePriceRole) + return price->closePrice(); + else if (role == StockModel::HighPriceRole) + return price->highPrice(); + else if (role == StockModel::LowPriceRole) + return price->lowPrice(); + else if (role == StockModel::AdjustedPriceRole) + return price->adjustedPrice(); + else if (role == StockModel::VolumeRole) + return price->volume(); + else if (role == StockModel::SectionRole) + return price->date().year(); + return QVariant(); +} + +QString StockModel::stockName() const +{ + return _stockName; +} +void StockModel::setStockName(const QString& name) +{ + if (_stockName != name) { + _stockName = name; + emit stockNameChanged(); + } +} + +QDate StockModel::startDate() const +{ + return _startDate; +} +void StockModel::setStartDate(const QDate& date) +{ + if (_startDate.isValid() && _startDate != date) { + _startDate = date; + emit startDateChanged(); + } +} + +QDate StockModel::endDate() const +{ + return _endDate; +} +void StockModel::setEndDate(const QDate& date) +{ + if (_endDate.isValid() && _endDate != date) { + _endDate = date; + emit endDateChanged(); + } +} + +StockModel::StockDataCycle StockModel::dataCycle() const +{ + return _dataCycle; +} + +QString StockModel::dataCycleString() const +{ + switch (_dataCycle) { + case StockModel::Daily: + return QString('d'); + break; + case StockModel::Weekly: + return QString('w'); + case StockModel::Monthly: + return QString('m'); + case StockModel::Dividend: + return QString('v'); + } + + return QString('d'); +} + + +void StockModel::setDataCycle(StockModel::StockDataCycle cycle) +{ + if (_dataCycle != cycle) { + _dataCycle = cycle; + emit dataCycleChanged(); + } +} diff --git a/examples/demos/stockchart/model.h b/examples/demos/stockchart/model.h new file mode 100644 index 0000000000..95e6f4891c --- /dev/null +++ b/examples/demos/stockchart/model.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +class StockPrice : public QObject +{ + Q_OBJECT + Q_PROPERTY(QDate date READ date) + Q_PROPERTY(qreal openPrice READ openPrice) + Q_PROPERTY(qreal closePrice READ closePrice) + Q_PROPERTY(qreal highPrice READ highPrice) + Q_PROPERTY(qreal lowPrice READ lowPrice) + Q_PROPERTY(qint32 volume READ volume) + Q_PROPERTY(qreal adjustedPrice READ adjustedPrice) +public: + + StockPrice(QObject *parent = 0) + : QObject(parent) + , _openPrice(-1) + , _closePrice(-1) + , _highPrice(-1) + , _lowPrice(-1) + , _volume(-1) + , _adjustedPrice(-1) + { + } + QDate date() const {return _date;} + qreal openPrice() const {return _openPrice; } + qreal closePrice() const {return _closePrice;} + qreal highPrice() const {return _highPrice;} + qreal lowPrice() const{return _lowPrice;} + qreal adjustedPrice() const{return _adjustedPrice;} + qint32 volume() const{return _volume;} + + void setDate(const QDate& date){_date = date;} + void setOpenPrice(qreal price){_openPrice = price;} + void setClosePrice(qreal price){_closePrice = price;} + void setHighPrice(qreal price){_highPrice = price;} + void setLowPrice(qreal price){_lowPrice = price;} + void setAdjustedPrice(qreal price) {_adjustedPrice = price;} + void setVolume(qint32 volume) {_volume = volume;} + +private: + QDate _date; + qreal _openPrice; + qreal _closePrice; + qreal _highPrice; + qreal _lowPrice; + qint32 _volume; + qreal _adjustedPrice; +}; + +class QNetworkReply; +class QNetworkAccessManager; +class StockModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(QString stockName READ stockName WRITE setStockName NOTIFY stockNameChanged) + Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) + Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged) + Q_PROPERTY(StockDataCycle dataCycle READ dataCycle WRITE setDataCycle NOTIFY dataCycleChanged) + + Q_ENUMS(StockDataCycle) +public: + enum StockDataCycle { + Daily, + Weekly, + Monthly, + Dividend + }; + + enum StockModelRoles { + DateRole = Qt::UserRole + 1, + SectionRole, + OpenPriceRole, + ClosePriceRole, + HighPriceRole, + LowPriceRole, + VolumeRole, + AdjustedPriceRole + }; + + StockModel(QObject *parent = 0); + + QString stockName() const; + void setStockName(const QString& name); + + QDate startDate() const; + void setStartDate(const QDate& date); + + QDate endDate() const; + void setEndDate(const QDate& date); + + StockDataCycle dataCycle() const; + void setDataCycle(StockDataCycle cycle); + + int rowCount(const QModelIndex & parent = QModelIndex()) const; + + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + +signals: + void stockNameChanged(); + void startDateChanged(); + void endDateChanged(); + void dataCycleChanged(); + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + +public slots: + void requestData(); + StockPrice* stockPriceAtIndex(int idx) const; +private slots: + void doRequest(); + void update(QNetworkReply* reply); +private: + QString dataCycleString() const; + QList _prices; + QString _stockName; + QDate _startDate; + QDate _endDate; + StockDataCycle _dataCycle; + QNetworkAccessManager* _manager; + bool _updating; +}; + + + + diff --git a/examples/demos/stockchart/plugin.cpp b/examples/demos/stockchart/plugin.cpp new file mode 100644 index 0000000000..3b354e2b31 --- /dev/null +++ b/examples/demos/stockchart/plugin.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "model.h" + +class QStockChartExampleQmlPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT +public: + void registerTypes(const char *uri) + { + Q_ASSERT(uri == QLatin1String("com.nokia.StockChartExample")); + qmlRegisterType(uri, 1, 0, "StockModel"); + qmlRegisterType(uri, 1, 0, "StockPrice"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(qmlstockchartexampleplugin, QStockChartExampleQmlPlugin); diff --git a/examples/demos/stockchart/stock.qml b/examples/demos/stockchart/stock.qml new file mode 100644 index 0000000000..1c95fde2ce --- /dev/null +++ b/examples/demos/stockchart/stock.qml @@ -0,0 +1,726 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.0 +import com.nokia.StockChartExample 1.0 +import "../contents" + +Rectangle { + id:container + width: 360; height: 600 + color: "#343434"; + Image { source: "contents/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 1 } + + + TitleBar { + id: titleBar + width: parent.width + anchors.top : container.top + height: 40 + opacity: 0.9 + } + + StockModel { + id:stockModel + dataCycle: StockModel.Daily + function dataCycleName() { + if (dataCycle === StockModel.Weekly) + return "Weekly"; + else if (dataCycle === StockModel.Monthly) + return "Monthly"; + return "Daily"; + } + + onDataChanged: { + if (view.viewType == "chart") { + canvas.requestPaint(); + } + } + onDownloadProgress: { + if (bytesReceived == bytesTotal && bytesTotal != -1) { + progress.opacity = 0; + } else { + progress.opacity = 0.8; + progress.text = "downloading " + stockModel.dataCycleName() + " data ..."+ Math.round(bytesReceived/1000) + " KB"; + } + } + + property string description:""; + } + + Stocks {id:stocks} + + Rectangle { + id: header + width: parent.width + height: 20 + color: "steelblue" + opacity: 0 + Row { + spacing: 2 + Text { + id:t + font.pointSize:15 + horizontalAlignment:Text.AlignHCenter + font.bold: true + font.underline:true + } + Rectangle { + height:20 + width:50 + Text {text:"Stock list"; font.pointSize:15; font.bold: true} + } + } + } + + ListView { + id:stockList + width: parent.width + anchors.bottom: container.bottom + anchors.top : titleBar.bottom + focus: true + keyNavigationWraps: true + spacing:1 + opacity: 1 + model: stocks + + Component.onCompleted: opacity = 0.9; + onOpacityChanged: { + titleBar.title = "Top 100 NASDAQ stocks" + } + + + delegate : Rectangle { + height: 30 + width: view.width + color: { + if (ListView.isCurrentItem) + return focus ? "lightyellow" : "pink"; + return index % 2 == 0 ? "lightblue" : "lightsteelblue" + } + Text { + font.pointSize:20 + text: index + ". " + stockId + " \t(" + name + ")"; + } + MouseArea { + anchors.fill: parent; + onDoubleClicked: { + stockList.opacity = 0; + stockModel.stockName = stockId; + stockModel.description = "NASDAQ:" + stockId + " (" + name + ")"; + view.opacity = 1; + view.viewType = "chart"; + canvas.opacity = 0.7; + } + onClicked: stockList.currentIndex = index + }//mousearea + }//delegate + } + + ListView { + id:view + width: container.width + height: container.height - 50 + anchors.bottom: container.bottom + focus: true + keyNavigationWraps: true + + spacing:1 + opacity: 0 + model: stockModel + highlightFollowsCurrentItem: false + highlightRangeMode: ListView.StrictlyEnforceRange + preferredHighlightBegin:50 + preferredHighlightEnd : height - 50 + highlight: listHighlight + + //header : Text {} + delegate: listDelegate + snapMode: ListView.SnapToItem + + property string viewType : "list" + property int topIndex:indexAt(0,contentY); + property int bottomIndex:indexAt(0, contentY+height); + + onCountChanged: { + + titleBar.title = stockModel.description + " " + Qt.formatDate(stockModel.startDate, "yyyy-MM-dd") + " - " + + Qt.formatDate(stockModel.endDate, "yyyy-MM-dd") + " " + stockModel.dataCycleName() + + " records:" + view.count; + + } + + Component { + id: listDelegate + Rectangle { + height: 20 + width: view.width + border.color: "lightsteelblue" + border.width: 1 + color: { + if (ListView.isCurrentItem) + return focus ? "lightyellow" : "pink"; + + return index % 2 == 0 ? "lightblue" : "lightsteelblue" + } + Text { + font.pointSize:13 + text: index + ". " + Qt.formatDate(date, "yyyy-MM-dd") + + "\t " + Math.round(openPrice*100)/100 + + "\t " + Math.round(highPrice*100)/100 + + "\t " + Math.round(lowPrice*100)/100 + + "\t " + Math.round(closePrice*100)/100 + + "\t " + volume + "\t " + + Math.round(adjustedPrice*100)/100; + } + MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} + } + } + + Component { + id: chartDelegate + Rectangle { + height: 20 + width: view.width/view.count * canvas.scaleX + border.color: "lightsteelblue" + border.width: 1 + color: { + if (ListView.isCurrentItem) + return focus ? "lightyellow" : "pink"; + + return index % 2 == 0 ? "lightblue" : "lightsteelblue" + } + + Text { + anchors.bottom: parent.bottom + font.pointSize: { + if (parent.width <= 4) + return 1; + if (parent.width <= 50) + return parent.width/4; + return 15; + } + horizontalAlignment:Text.AlignHCenter + verticalAlignment:Text.AlignBottom + text:font.pointSize > 1 ? Qt.formatDate(date, "d/M/yy") : "" + } + MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} + } + } + + Component { + id:chartHighlight + Rectangle { radius: 5; width:40; height: 20; color: "lightsteelblue" } + } + + Component { + id:listHighlight + Rectangle { radius: 5; width:container.width; height: 20; color: "lightsteelblue" } + } + + + + + onViewTypeChanged : { + if (viewType == "list") { + view.orientation = ListView.Vertical; + view.delegate = listDelegate; +// view.section.property = "year"; +// view.section.criteria = ViewSection.FullString; +// view.section.delegate = sectionHeading; + view.highlight = listHighlight; + view.opacity = 1; + canvas.opacity = 0; + // comment.opacity = 0; + + } else if (viewType == "chart") { + view.orientation = ListView.Horizontal; + view.delegate = chartDelegate; + //comment.opacity = 0.6; + + view.opacity = 1; + view.height = 30 + + canvas.opacity = 0.7; + canvas.requestPaint(); + } else { + viewType = "list"; + } + } + + + onCurrentIndexChanged: { + //header.updateCurrent(stockModel.stockPriceAtIndex(view.currentIndex)); + if (viewType == "chart") { + canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); + canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); + + canvas.requestPaint(); + } + } + onContentYChanged: { // keep "current" item visible + topIndex = indexAt(0,contentY); + bottomIndex = indexAt(0, contentY+height); + + if (topIndex != -1 && currentIndex <= topIndex) + currentIndex = topIndex+1; + else if (bottomIndex != -1 && currentIndex >= bottomIndex) + currentIndex = bottomIndex-1; + if (viewType == "chart") + canvas.requestPaint(); + } + + onContentXChanged: { // keep "current" item visible + topIndex = indexAt(contentX,0); + bottomIndex = indexAt(contentX+width, 0); + + if (topIndex != -1 && currentIndex <= topIndex) + currentIndex = topIndex+1; + else if (bottomIndex != -1 && currentIndex >= bottomIndex) + currentIndex = bottomIndex-1; + if (viewType == "chart") + canvas.requestPaint(); + } + + MouseArea { + anchors.fill: parent + onDoubleClicked: { + if (view.viewType == "list") + view.viewType = "chart"; + else + view.viewType = "list"; + } + } + } + + + + Canvas { + id:canvas + anchors.top : titleBar.bottom + anchors.bottom : view.top + width:container.width; + opacity:0 + renderTarget: Canvas.Image + renderStrategy: Canvas.Immediate + property bool running:false + property int frames:first + property int mouseX:0; + property int mouseY:0; + property int mousePressedX:0; + property int mousePressedY:0; + property int movedY:0 + property real scaleX:1.0; + property real scaleY:1.0; + property int first:0; + property int last:view.count - 1; + + onOpacityChanged: { + if (opacity > 0) + requestPaint(); + } + Text { + id:comment + x:100 + y:50 + font.pointSize: 20 + color:"white" + opacity: 0.7 + focus:false + text: stockModel.description + function updateCurrent(price) + { + if (price !== undefined) { + text =stockModel.description + "\n" + + Qt.formatDate(price.date, "yyyy-MM-dd") + " OPEN:" + + Math.round(price.openPrice*100)/100 + " HIGH:" + + Math.round(price.highPrice*100)/100 + " LOW:" + + Math.round(price.lowPrice*100)/100 + " CLOSE:" + + Math.round(price.closePrice*100)/100 + " VOLUME:" + + price.volume; + } + } + } + + Text { + id:priceAxis + x:25 + y:25 + font.pointSize: 15 + color:"yellow" + opacity: 0.7 + focus: false + } + Text { + id:volumeAxis + x:canvas.width - 200 + y:25 + font.pointSize: 15 + color:"yellow" + opacity: 0.7 + } + + Rectangle { + id:progress + x:canvas.width/2 - 100 + y:canvas.height/2 + width:childrenRect.width + height: childrenRect.height + opacity: 0 + color:"white" + property string text; + Text { + text:parent.text + font.pointSize: 20 + } + } + + Button { + id:runButton + text:"Run this chart" + y:0 + x:canvas.width/2 - 50 + opacity: 0.5 + onClicked: { + if (canvas.running) { + canvas.running = false; + canvas.frames = canvas.first; + canvas.requestPaint(); + text = "Run this chart"; + comment.text = stockModel.description; + } else { + text = " Stop running "; + canvas.runChart(); + } + } + } + Button { + id:returnButton + text:"Stocks" + y:0 + anchors.left : runButton.right + anchors.leftMargin : 20 + opacity: 0.5 + onClicked: { + stockList.opacity = 1; + canvas.opacity = 0; + } + } + PinchArea { + anchors.fill: parent + onPinchUpdated : { + var current = pinch.center; + var scale = pinch.scale; + console.log("center:" + pinch.center + " scale:" + pinch.scale); + //canvas.requestPaint(); + } + } + + MouseArea { + anchors.fill: parent + + onDoubleClicked: { + if (stockModel.dataCycle == StockModel.Daily) + stockModel.dataCycle = StockModel.Weekly; + else if (stockModel.dataCycle == StockModel.Weekly) + stockModel.dataCycle = StockModel.Monthly; + else + stockModel.dataCycle = StockModel.Daily; + } + + onPositionChanged: { + if (mouse.modifiers & Qt.ControlModifier) { + if (canvas.mouseX == 0 && canvas.mouseY == 0) { + canvas.mouseX = mouse.x; + canvas.mouseY = mouse.y; + } + } else{ + var w = (view.width/view.count)*canvas.scaleX; + + //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2); + + var movedX = Math.round((canvas.mousePressedX - mouse.x)/w); + if (movedX != 0 || canvas.movedY != 0) { + if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) { + canvas.first += movedX; + canvas.last += movedX; + } + canvas.requestPaint(); + } + } + } + + onPressed: { + canvas.mousePressedX = mouse.x; + canvas.mousePressedY = mouse.y; + } + + onReleased : { + if (mouse.modifiers & Qt.ControlModifier) { + var sx = mouse.x - canvas.mouseX; + var sy = canvas.mouseY - mouse.y; + + if (Math.abs(sx) < 50) sx = 0; + if (Math.abs(sy) < 50) sy = 0; + + if (sx > 0) + canvas.scaleX *= sx/100 +1; + else + canvas.scaleX *= 1/(-sx/100 + 1); + + if (sy > 0) + canvas.scaleY *= sy/100 +1; + else + canvas.scaleY *= 1/(-sy/100 + 1); + + if (canvas.scaleX < 1) + canvas.scaleX = 1; + + //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY); + + canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); + canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); + + canvas.mouseX = 0; + canvas.mouseY = 0; + canvas.mousePressedX = 0; + canvas.mousePressedY = 0; + canvas.requestPaint(); + } + } + } + + function runChart() { + canvas.running = true; + requestPaint(); + } + + function showPriceAt(x) { + var w = (view.width/view.count)*canvas.scaleX; + //header.updateCurrent(stockModel.stockPriceAtIndex(canvas.first + Math.round(x/w))); + //console.log("x:" + x + " w:" + w + " index:" + (canvas.first + Math.round(x/w))); + } + + function drawPrice(ctx, from, to, color, price, points, highest) + { + ctx.globalAlpha = 0.7; + ctx.strokeStyle = color; + ctx.lineWidth = 1; + ctx.beginPath(); + + //price x axis + priceAxis.text = "price:" + Math.round(highest); + ctx.font = "bold 12px sans-serif"; + + ctx.strokeText("price", 25, 25); + for (var j = 1; j < 30; j++) { + var val = (highest * j) / 30; + val = canvas.height * (1 - val/highest); + ctx.beginPath(); + + ctx.moveTo(10, val); + if (j % 5) + ctx.lineTo(15, val); + else + ctx.lineTo(20, val); + ctx.stroke(); + } + + ctx.beginPath(); + ctx.moveTo(10, 0); + ctx.lineTo(10, canvas.height); + ctx.stroke(); + + + var w = canvas.width/points.length; + var end = canvas.running? canvas.frames - canvas.first :points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var y = points[i][price]; + y += canvas.movedY; + + y = canvas.height * (1 - y/highest); + if (i == 0) { + ctx.moveTo(x+w/2, y); + } else { + ctx.lineTo(x+w/2, y); + } + } + ctx.stroke(); + } + + function drawKLine(ctx, from, to, points, highest) + { + ctx.globalAlpha = 0.4; + ctx.lineWidth = 2; + var end = canvas.running? canvas.frames - canvas.first :points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var open = canvas.height * (1 - points[i].open/highest) - canvas.movedY; + var close = canvas.height * (1 - points[i].close/highest) - canvas.movedY; + var high = canvas.height * (1 - points[i].high/highest) - canvas.movedY; + var low = canvas.height * (1 - points[i].low/highest) - canvas.movedY; + + var top, bottom; + if (close <= open) { + ctx.fillStyle = Qt.rgba(1, 0, 0, 1); + ctx.strokeStyle = Qt.rgba(1, 0, 0, 1); + top = close; + bottom = open; + } else { + ctx.fillStyle = Qt.rgba(0, 1, 0, 1); + ctx.strokeStyle = Qt.rgba(0, 1, 0, 1); + top = open; + bottom = close; + } + + var w1, w2; + w1 = canvas.width/points.length; + w2 = w1 > 10 ? w1/2 : w1; + + ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top); + ctx.beginPath(); + ctx.moveTo(x+w1/2, high); + ctx.lineTo(x+w1/2, low); + ctx.stroke(); + } + ctx.globalAlpha = 1; + + } + + function drawVolume(ctx, from, to, color, price, points, highest) + { + ctx.fillStyle = color; + ctx.globalAlpha = 0.6; + ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1); + ctx.lineWidth = 1; + + //volume x axis + volumeAxis.text = "volume:" + Math.round(highest/(1000*100)) + "M"; + for (var j = 1; j < 30; j++) { + var val = (highest * j) / 30; + val = canvas.height * (1 - val/highest); + ctx.beginPath(); + if (j % 5) + ctx.moveTo(canvas.width - 15, val); + else + ctx.moveTo(canvas.width - 20, val); + ctx.lineTo(canvas.width - 10, val); + ctx.stroke(); + } + + ctx.beginPath(); + ctx.moveTo(canvas.width - 10, 0); + ctx.lineTo(canvas.width - 10, canvas.height); + ctx.stroke(); + + var end = canvas.running? canvas.frames - canvas.first :points.length; + for (var i = 0; i < end; i++) { + var x = points[i].x; + var y = points[i][price]; + y = canvas.height * (1 - y/highest); + ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y); + } + } +/* + onPainted : { + if (canvas.running) { + if (frames >= last) { + canvas.running = false; + canvas.frames = first; + runButton.text = "Run this chart"; + comment.text = stockModel.description; + requestPaint(); + } else { + frames += Math.round(view.count / 100); + if (frames > last) frames = last; + var price = stockModel.stockPriceAtIndex(frames); + if (price) { + comment.updateCurrent(price); + } + + requestPaint(); + } + } + } +*/ + onPaint: { + if (view.currentIndex <= 0) + first = 0; + if (last >= view.count) + last = view.count - 1; + + //console.log("painting... first:" + first + ", last:" + last + " current:" + view.currentIndex); + var ctx = canvas.getContext("2d"); + ctx.save(); + + ctx.globalCompositeOperation = "source-over"; + ctx.lineWidth = 1; + ctx.lineJoin = "round"; + ctx.fillStyle = "rgba(0,0,0,0)"; + + ctx.fillRect(0, 0, canvas.width, canvas.height); + + + + var highestPrice = 500/canvas.scaleY; + var highestValume = 600 * 1000 * 1000/canvas.scaleY; + var points = []; + for (var i = 0; i <= last - first; i++) { + var price = stockModel.stockPriceAtIndex(i + first); + points.push({ + x: i*canvas.width/(last-first+1), + open: price.openPrice, + close: price.closePrice, + high:price.highPrice, + low:price.lowPrice, + volume:price.volume + }); + } + + drawPrice(ctx, first, last, Qt.rgba(1, 0, 0, 1),"high", points, highestPrice); + drawPrice(ctx, first, last, Qt.rgba(0, 1, 0, 1),"low", points, highestPrice); + drawPrice(ctx, first, last, Qt.rgba(0, 0, 1, 1),"open", points, highestPrice); + drawPrice(ctx, first, last, Qt.rgba(0.5, 0.5, 0.5, 1),"close", points, highestPrice); + drawVolume(ctx, first, last, Qt.rgba(0.3, 0.5, 0.7, 1),"volume", points, highestValume); + drawKLine(ctx, first, last, points, highestPrice); + ctx.restore(); + } + } +} diff --git a/examples/demos/stockchart/stockchart.pro b/examples/demos/stockchart/stockchart.pro new file mode 100644 index 0000000000..e368746db5 --- /dev/null +++ b/examples/demos/stockchart/stockchart.pro @@ -0,0 +1,20 @@ +TEMPLATE = lib +CONFIG += qt plugin +QT += qml network + +DESTDIR = com/nokia/StockChartExample +TARGET = qmlstockchartexampleplugin + +SOURCES += model.cpp plugin.cpp +HEADERS += model.h +qdeclarativesources.files += \ + com/nokia/StockChartExample/qmldir \ + stock.qml + +qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample + +sources.files += stockchart.pro model.h model.cpp plugin.cpp README +sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins +target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample + +INSTALLS += qdeclarativesources sources target diff --git a/examples/demos/stockchart/stockchart.qmlproject b/examples/demos/stockchart/stockchart.qmlproject new file mode 100644 index 0000000000..5f2b9094b3 --- /dev/null +++ b/examples/demos/stockchart/stockchart.qmlproject @@ -0,0 +1,16 @@ +import QmlProject 1.1 + +Project { + mainFile: "stock.qml" + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } +} \ No newline at end of file diff --git a/examples/demos/twitterfriends/TwitterUser.qml b/examples/demos/twitterfriends/TwitterUser.qml new file mode 100644 index 0000000000..8b906216ef --- /dev/null +++ b/examples/demos/twitterfriends/TwitterUser.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id:twitterUser + property variant friends : []; + property string name : ""; + property string twitterId : ""; + property string image : ""; + property string url : ""; + property string desc : ""; + width : 0; + height : 0; + property int posX:0; + property int posY:0; + property bool hasFocus : false; + property variant canvas; + property variant manager; + property variant linkColor; + property bool selected : false; + + Rectangle { + id:twitterStatus + x:twitterUser.width + y:twitterUser.height + width:250 + height:60 + opacity: 0 + border.color:"steelblue" + border.width:3 + Column { + spacing:2 + Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere} + Text {color:"steelblue"; font.pointSize:8; width:250; height:30; text:twitterUser.url; wrapMode: Text.WrapAnywhere} + } + } + + function moved() { + twitterUser.posX = twitterUser.x; + twitterUser.posY = twitterUser.y; + twitterUser.canvas.requestPaint(); + } + + onXChanged: moved(); + onYChanged: moved(); + + MouseArea { + anchors.fill:parent + drag.target : twitterUser + drag.axis : Drag.XandYAxis + + onClicked: { + if (!twitterUser.selected) { + twitterUser.selected = true; + twitterStatus.opacity = 1; + twitterStatus.visible = true; + } else { + twitterUser.selected = false; + twitterStatus.opacity = 0; + } + } + + onDoubleClicked : { + twitterStatus.opacity = 0; + twitterUser.selected = false; + twitterUser.hasFocus = true; + twitterUser.canvas.twitterName = twitterUser.name; + twitterUser.canvas.twitterId = twitterUser.twitterId; + twitterUser.canvas.loading = true; + twitterUser.createFriends(); + } + } + + function show(ctx, layoutChanged) { + var w = canvas.width; + var h = canvas.height; + if (twitterUser.hasFocus) { + twitterUser.width = 60 + twitterUser.height = 60 + twitterUser.posX = w/2; + twitterUser.posY = h/2; + } else { + twitterUser.width = 40 + twitterUser.height = 40 + } + + + if (twitterUser.hasFocus) { + if (layoutChanged) + twitterUser.layoutFriends(); + twitterUser.linkFriends(ctx); + twitterUser.showFriends(ctx); + ctx.shadowOffsetX = 5; + ctx.shadowOffsetY = 5; + ctx.shadowBlur = 7; + ctx.shadowColor = "blue"; + ctx.globalAlpha = 1; + } else { + ctx.shadowOffsetX = 5; + ctx.shadowOffsetY = 5; + ctx.shadowBlur = 7; + ctx.shadowColor = twitterUser.linkColor; + ctx.globalAlpha = 0.6; + } + + if (twitterUser.canvas.isImageLoaded(twitterUser.image)) { + ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height); + } +// ctx.font = "15px"; +// var nameSize = ctx.measureText(twitterUser.name).width; +// ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10); + } + function dump() { + console.log("name:" + twitterUser.name + + " x:" + twitterUser.posX + + " y:" + twitterUser.posY + + " width:" + twitterUser.width + + " height:" + twitterUser.height + + " id:" + twitterUser.twitterId + + " image:" + twitterUser.image + + " url:" + twitterUser.url + "\n" + twitterUser.desc); + } + + function layoutFriends() { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend) { + friend.x = Math.random() *w; + friend.y = Math.random() *h; + } + } + } + + function showFriends(ctx) { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length && i < 15; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { + friend.hasFocus = false; + friend.show(ctx, false); + } + } + } + + function linkFriends(ctx) { + var w = canvas.width; + var h = canvas.height; + for (var i=0; i < twitterUser.friends.length && i < 15; i++) { + var friend = manager.getById(twitterUser.friends[i]); + if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { + if (!friend.linkColor) + friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255 + , ((Math.random() * 200) +55)/255 + , ((Math.random() * 200) +55)/255, 0.8); + ctx.strokeStyle = friend.linkColor; + ctx.lineWidth = 8; + ctx.beginPath(); + ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2); + ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2); + ctx.stroke(); + } + } + } + + + function create(url) { + var x = new XMLHttpRequest; + x.open("GET", url); + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + var user = eval('(' + x.responseText +')')[0]; + twitterUser.name = user.name; + twitterUser.twitterId = user.id; + twitterUser.image = user.profile_image_url; + twitterUser.canvas.loadImage(twitterUser.image); + twitterUser.url = user.url; + twitterUser.desc = user.description; + twitterUser.createFriends(); + } + } + x.send(); + } + + function createByName(name) { + if (twitterUser.name === "" && twitterUser.twitterId === "") { + twitterUser.name = name; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name; + twitterUser.create(userUrl); + } + } + + function createById(id) { + if (twitterUser.name === "" && twitterUser.twitterId === "") { + twitterUser.twitterId = id; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id; + twitterUser.create(userUrl); + } + } + + function createFriends() { + if (twitterUser.friends.length === 0) { + var x = new XMLHttpRequest; + var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId; + x.open("GET", friendsUrl); + + x.onreadystatechange = function() { + if (x.readyState == XMLHttpRequest.DONE) { + twitterUser.friends = eval('(' + x.responseText +')').ids; + var doRequest = false; + var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id="; + + for (var i=0; i -#include -#include -#include -#include - -#include -#include - -StockModel::StockModel(QObject *parent) - : QAbstractListModel(parent) - , _startDate(QDate(1995, 4, 25)) - , _endDate(QDate::currentDate()) - , _dataCycle(StockModel::Daily) - , _manager(0) - , _updating(false) -{ - QHash roles; - roles[StockModel::DateRole] = "date"; - roles[StockModel::SectionRole] = "year"; - roles[StockModel::OpenPriceRole] = "openPrice"; - roles[StockModel::ClosePriceRole] = "closePrice"; - roles[StockModel::HighPriceRole] = "highPrice"; - roles[StockModel::LowPriceRole] = "lowPrice"; - roles[StockModel::VolumeRole] = "volume"; - roles[StockModel::AdjustedPriceRole] = "adjustedPrice"; - setRoleNames(roles); - - connect(this, SIGNAL(stockNameChanged()), SLOT(requestData())); - connect(this, SIGNAL(startDateChanged()), SLOT(requestData())); - connect(this, SIGNAL(endDateChanged()), SLOT(requestData())); - connect(this, SIGNAL(dataCycleChanged()), SLOT(requestData())); - - _manager = new QNetworkAccessManager(this); - connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(update(QNetworkReply*))); - -} - -int StockModel::rowCount(const QModelIndex & parent) const { - Q_UNUSED(parent); - return _prices.count(); -} - -StockPrice* StockModel::stockPriceAtIndex(int idx) const -{ - if (idx >=0 && idx < _prices.size()) { - return _prices[idx]; - } - return 0; -} - - -void StockModel::requestData() -{ - if (!_updating) { - _updating = true; - QMetaObject::invokeMethod(this, "doRequest", Qt::QueuedConnection); - } -} - -void StockModel::doRequest() -{ - /* - Fetch stock data from yahoo finance: - url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv - s:stock name/id, a:start day, b:start month, c:start year default: 25 April 1995, oldest c= 1962 - d:end day, e:end month, f:end year, default:today (data only available 3 days before today) - g:data cycle(d daily, w weekly, m monthly, v Dividend) - */ - if (_manager && !_stockName.isEmpty() && _endDate > _startDate) { - QString query("http://ichart.finance.yahoo.com/table.csv?s=%1&a=%2&b=%3&c=%4&d=%5&e=%6&f=%7&g=%8&ignore=.csv"); - query = query.arg(_stockName) - .arg(_startDate.day()).arg(_startDate.month()).arg(_startDate.year()) - .arg(_endDate.day()).arg(_endDate.month()).arg(_endDate.year()) - .arg(dataCycleString()); - - qDebug() << "request stock data:" << query; - QNetworkReply* reply = _manager->get(QNetworkRequest(QUrl(query))); - connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(downloadProgress(qint64,qint64))); - } -} - -void StockModel::update(QNetworkReply *reply) -{ - _updating = false; - - if (reply) { - if (reply->error() == QNetworkReply::NoError) { - beginResetModel(); - - foreach (StockPrice* p, _prices) { - p->deleteLater(); - } - - _prices.clear(); - - while (!reply->atEnd()) { - QString line = reply->readLine(); - QStringList fields = line.split(','); - - //data format:Date,Open,High,Low,Close,Volume,Adjusted close price - //example: 2011-06-24,6.03,6.04,5.88,5.88,20465200,5.88 - if (fields.size() == 7) { - StockPrice* price = new StockPrice(this); - price->setDate(QDate::fromString(fields[0], Qt::ISODate)); - price->setOpenPrice(fields[1].toFloat()); - price->setHighPrice(fields[2].toFloat()); - price->setLowPrice(fields[3].toFloat()); - price->setClosePrice(fields[4].toFloat()); - price->setVolume(fields[5].toInt()); - price->setAdjustedPrice(fields[6].toFloat()); - _prices.prepend(price); - } - } - qDebug() << "get stock data successfully, total:" << _prices.count() << "records."; - } else { - qDebug() << "get stock data failed:" << reply->errorString(); - } - reply->deleteLater(); - endResetModel(); - emit dataChanged(QModelIndex(), QModelIndex()); - } -} - -QVariant StockModel::data(const QModelIndex & index, int role) const { - if (index.row() < 0 || index.row() > _prices.count()) - return QVariant(); - - const StockPrice* price = _prices[index.row()]; - if (role == StockModel::DateRole) - return price->date(); - else if (role == StockModel::OpenPriceRole) - return price->openPrice(); - else if (role == StockModel::ClosePriceRole) - return price->closePrice(); - else if (role == StockModel::HighPriceRole) - return price->highPrice(); - else if (role == StockModel::LowPriceRole) - return price->lowPrice(); - else if (role == StockModel::AdjustedPriceRole) - return price->adjustedPrice(); - else if (role == StockModel::VolumeRole) - return price->volume(); - else if (role == StockModel::SectionRole) - return price->date().year(); - return QVariant(); -} - -QString StockModel::stockName() const -{ - return _stockName; -} -void StockModel::setStockName(const QString& name) -{ - if (_stockName != name) { - _stockName = name; - emit stockNameChanged(); - } -} - -QDate StockModel::startDate() const -{ - return _startDate; -} -void StockModel::setStartDate(const QDate& date) -{ - if (_startDate.isValid() && _startDate != date) { - _startDate = date; - emit startDateChanged(); - } -} - -QDate StockModel::endDate() const -{ - return _endDate; -} -void StockModel::setEndDate(const QDate& date) -{ - if (_endDate.isValid() && _endDate != date) { - _endDate = date; - emit endDateChanged(); - } -} - -StockModel::StockDataCycle StockModel::dataCycle() const -{ - return _dataCycle; -} - -QString StockModel::dataCycleString() const -{ - switch (_dataCycle) { - case StockModel::Daily: - return QString('d'); - break; - case StockModel::Weekly: - return QString('w'); - case StockModel::Monthly: - return QString('m'); - case StockModel::Dividend: - return QString('v'); - } - - return QString('d'); -} - - -void StockModel::setDataCycle(StockModel::StockDataCycle cycle) -{ - if (_dataCycle != cycle) { - _dataCycle = cycle; - emit dataCycleChanged(); - } -} diff --git a/examples/quick/canvas/stockchart/model.h b/examples/quick/canvas/stockchart/model.h deleted file mode 100644 index 95e6f4891c..0000000000 --- a/examples/quick/canvas/stockchart/model.h +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include - -class StockPrice : public QObject -{ - Q_OBJECT - Q_PROPERTY(QDate date READ date) - Q_PROPERTY(qreal openPrice READ openPrice) - Q_PROPERTY(qreal closePrice READ closePrice) - Q_PROPERTY(qreal highPrice READ highPrice) - Q_PROPERTY(qreal lowPrice READ lowPrice) - Q_PROPERTY(qint32 volume READ volume) - Q_PROPERTY(qreal adjustedPrice READ adjustedPrice) -public: - - StockPrice(QObject *parent = 0) - : QObject(parent) - , _openPrice(-1) - , _closePrice(-1) - , _highPrice(-1) - , _lowPrice(-1) - , _volume(-1) - , _adjustedPrice(-1) - { - } - QDate date() const {return _date;} - qreal openPrice() const {return _openPrice; } - qreal closePrice() const {return _closePrice;} - qreal highPrice() const {return _highPrice;} - qreal lowPrice() const{return _lowPrice;} - qreal adjustedPrice() const{return _adjustedPrice;} - qint32 volume() const{return _volume;} - - void setDate(const QDate& date){_date = date;} - void setOpenPrice(qreal price){_openPrice = price;} - void setClosePrice(qreal price){_closePrice = price;} - void setHighPrice(qreal price){_highPrice = price;} - void setLowPrice(qreal price){_lowPrice = price;} - void setAdjustedPrice(qreal price) {_adjustedPrice = price;} - void setVolume(qint32 volume) {_volume = volume;} - -private: - QDate _date; - qreal _openPrice; - qreal _closePrice; - qreal _highPrice; - qreal _lowPrice; - qint32 _volume; - qreal _adjustedPrice; -}; - -class QNetworkReply; -class QNetworkAccessManager; -class StockModel : public QAbstractListModel -{ - Q_OBJECT - - Q_PROPERTY(QString stockName READ stockName WRITE setStockName NOTIFY stockNameChanged) - Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) - Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged) - Q_PROPERTY(StockDataCycle dataCycle READ dataCycle WRITE setDataCycle NOTIFY dataCycleChanged) - - Q_ENUMS(StockDataCycle) -public: - enum StockDataCycle { - Daily, - Weekly, - Monthly, - Dividend - }; - - enum StockModelRoles { - DateRole = Qt::UserRole + 1, - SectionRole, - OpenPriceRole, - ClosePriceRole, - HighPriceRole, - LowPriceRole, - VolumeRole, - AdjustedPriceRole - }; - - StockModel(QObject *parent = 0); - - QString stockName() const; - void setStockName(const QString& name); - - QDate startDate() const; - void setStartDate(const QDate& date); - - QDate endDate() const; - void setEndDate(const QDate& date); - - StockDataCycle dataCycle() const; - void setDataCycle(StockDataCycle cycle); - - int rowCount(const QModelIndex & parent = QModelIndex()) const; - - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; - -signals: - void stockNameChanged(); - void startDateChanged(); - void endDateChanged(); - void dataCycleChanged(); - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - -public slots: - void requestData(); - StockPrice* stockPriceAtIndex(int idx) const; -private slots: - void doRequest(); - void update(QNetworkReply* reply); -private: - QString dataCycleString() const; - QList _prices; - QString _stockName; - QDate _startDate; - QDate _endDate; - StockDataCycle _dataCycle; - QNetworkAccessManager* _manager; - bool _updating; -}; - - - - diff --git a/examples/quick/canvas/stockchart/plugin.cpp b/examples/quick/canvas/stockchart/plugin.cpp deleted file mode 100644 index 3b354e2b31..0000000000 --- a/examples/quick/canvas/stockchart/plugin.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "model.h" - -class QStockChartExampleQmlPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT -public: - void registerTypes(const char *uri) - { - Q_ASSERT(uri == QLatin1String("com.nokia.StockChartExample")); - qmlRegisterType(uri, 1, 0, "StockModel"); - qmlRegisterType(uri, 1, 0, "StockPrice"); - } -}; - -#include "plugin.moc" - -Q_EXPORT_PLUGIN2(qmlstockchartexampleplugin, QStockChartExampleQmlPlugin); diff --git a/examples/quick/canvas/stockchart/stock.qml b/examples/quick/canvas/stockchart/stock.qml deleted file mode 100644 index 1c95fde2ce..0000000000 --- a/examples/quick/canvas/stockchart/stock.qml +++ /dev/null @@ -1,726 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.0 -import com.nokia.StockChartExample 1.0 -import "../contents" - -Rectangle { - id:container - width: 360; height: 600 - color: "#343434"; - Image { source: "contents/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 1 } - - - TitleBar { - id: titleBar - width: parent.width - anchors.top : container.top - height: 40 - opacity: 0.9 - } - - StockModel { - id:stockModel - dataCycle: StockModel.Daily - function dataCycleName() { - if (dataCycle === StockModel.Weekly) - return "Weekly"; - else if (dataCycle === StockModel.Monthly) - return "Monthly"; - return "Daily"; - } - - onDataChanged: { - if (view.viewType == "chart") { - canvas.requestPaint(); - } - } - onDownloadProgress: { - if (bytesReceived == bytesTotal && bytesTotal != -1) { - progress.opacity = 0; - } else { - progress.opacity = 0.8; - progress.text = "downloading " + stockModel.dataCycleName() + " data ..."+ Math.round(bytesReceived/1000) + " KB"; - } - } - - property string description:""; - } - - Stocks {id:stocks} - - Rectangle { - id: header - width: parent.width - height: 20 - color: "steelblue" - opacity: 0 - Row { - spacing: 2 - Text { - id:t - font.pointSize:15 - horizontalAlignment:Text.AlignHCenter - font.bold: true - font.underline:true - } - Rectangle { - height:20 - width:50 - Text {text:"Stock list"; font.pointSize:15; font.bold: true} - } - } - } - - ListView { - id:stockList - width: parent.width - anchors.bottom: container.bottom - anchors.top : titleBar.bottom - focus: true - keyNavigationWraps: true - spacing:1 - opacity: 1 - model: stocks - - Component.onCompleted: opacity = 0.9; - onOpacityChanged: { - titleBar.title = "Top 100 NASDAQ stocks" - } - - - delegate : Rectangle { - height: 30 - width: view.width - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - Text { - font.pointSize:20 - text: index + ". " + stockId + " \t(" + name + ")"; - } - MouseArea { - anchors.fill: parent; - onDoubleClicked: { - stockList.opacity = 0; - stockModel.stockName = stockId; - stockModel.description = "NASDAQ:" + stockId + " (" + name + ")"; - view.opacity = 1; - view.viewType = "chart"; - canvas.opacity = 0.7; - } - onClicked: stockList.currentIndex = index - }//mousearea - }//delegate - } - - ListView { - id:view - width: container.width - height: container.height - 50 - anchors.bottom: container.bottom - focus: true - keyNavigationWraps: true - - spacing:1 - opacity: 0 - model: stockModel - highlightFollowsCurrentItem: false - highlightRangeMode: ListView.StrictlyEnforceRange - preferredHighlightBegin:50 - preferredHighlightEnd : height - 50 - highlight: listHighlight - - //header : Text {} - delegate: listDelegate - snapMode: ListView.SnapToItem - - property string viewType : "list" - property int topIndex:indexAt(0,contentY); - property int bottomIndex:indexAt(0, contentY+height); - - onCountChanged: { - - titleBar.title = stockModel.description + " " + Qt.formatDate(stockModel.startDate, "yyyy-MM-dd") + " - " + - Qt.formatDate(stockModel.endDate, "yyyy-MM-dd") + " " + stockModel.dataCycleName() + - " records:" + view.count; - - } - - Component { - id: listDelegate - Rectangle { - height: 20 - width: view.width - border.color: "lightsteelblue" - border.width: 1 - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - Text { - font.pointSize:13 - text: index + ". " + Qt.formatDate(date, "yyyy-MM-dd") - + "\t " + Math.round(openPrice*100)/100 - + "\t " + Math.round(highPrice*100)/100 - + "\t " + Math.round(lowPrice*100)/100 - + "\t " + Math.round(closePrice*100)/100 - + "\t " + volume + "\t " - + Math.round(adjustedPrice*100)/100; - } - MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} - } - } - - Component { - id: chartDelegate - Rectangle { - height: 20 - width: view.width/view.count * canvas.scaleX - border.color: "lightsteelblue" - border.width: 1 - color: { - if (ListView.isCurrentItem) - return focus ? "lightyellow" : "pink"; - - return index % 2 == 0 ? "lightblue" : "lightsteelblue" - } - - Text { - anchors.bottom: parent.bottom - font.pointSize: { - if (parent.width <= 4) - return 1; - if (parent.width <= 50) - return parent.width/4; - return 15; - } - horizontalAlignment:Text.AlignHCenter - verticalAlignment:Text.AlignBottom - text:font.pointSize > 1 ? Qt.formatDate(date, "d/M/yy") : "" - } - MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index} - } - } - - Component { - id:chartHighlight - Rectangle { radius: 5; width:40; height: 20; color: "lightsteelblue" } - } - - Component { - id:listHighlight - Rectangle { radius: 5; width:container.width; height: 20; color: "lightsteelblue" } - } - - - - - onViewTypeChanged : { - if (viewType == "list") { - view.orientation = ListView.Vertical; - view.delegate = listDelegate; -// view.section.property = "year"; -// view.section.criteria = ViewSection.FullString; -// view.section.delegate = sectionHeading; - view.highlight = listHighlight; - view.opacity = 1; - canvas.opacity = 0; - // comment.opacity = 0; - - } else if (viewType == "chart") { - view.orientation = ListView.Horizontal; - view.delegate = chartDelegate; - //comment.opacity = 0.6; - - view.opacity = 1; - view.height = 30 - - canvas.opacity = 0.7; - canvas.requestPaint(); - } else { - viewType = "list"; - } - } - - - onCurrentIndexChanged: { - //header.updateCurrent(stockModel.stockPriceAtIndex(view.currentIndex)); - if (viewType == "chart") { - canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); - canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); - - canvas.requestPaint(); - } - } - onContentYChanged: { // keep "current" item visible - topIndex = indexAt(0,contentY); - bottomIndex = indexAt(0, contentY+height); - - if (topIndex != -1 && currentIndex <= topIndex) - currentIndex = topIndex+1; - else if (bottomIndex != -1 && currentIndex >= bottomIndex) - currentIndex = bottomIndex-1; - if (viewType == "chart") - canvas.requestPaint(); - } - - onContentXChanged: { // keep "current" item visible - topIndex = indexAt(contentX,0); - bottomIndex = indexAt(contentX+width, 0); - - if (topIndex != -1 && currentIndex <= topIndex) - currentIndex = topIndex+1; - else if (bottomIndex != -1 && currentIndex >= bottomIndex) - currentIndex = bottomIndex-1; - if (viewType == "chart") - canvas.requestPaint(); - } - - MouseArea { - anchors.fill: parent - onDoubleClicked: { - if (view.viewType == "list") - view.viewType = "chart"; - else - view.viewType = "list"; - } - } - } - - - - Canvas { - id:canvas - anchors.top : titleBar.bottom - anchors.bottom : view.top - width:container.width; - opacity:0 - renderTarget: Canvas.Image - renderStrategy: Canvas.Immediate - property bool running:false - property int frames:first - property int mouseX:0; - property int mouseY:0; - property int mousePressedX:0; - property int mousePressedY:0; - property int movedY:0 - property real scaleX:1.0; - property real scaleY:1.0; - property int first:0; - property int last:view.count - 1; - - onOpacityChanged: { - if (opacity > 0) - requestPaint(); - } - Text { - id:comment - x:100 - y:50 - font.pointSize: 20 - color:"white" - opacity: 0.7 - focus:false - text: stockModel.description - function updateCurrent(price) - { - if (price !== undefined) { - text =stockModel.description + "\n" - + Qt.formatDate(price.date, "yyyy-MM-dd") + " OPEN:" - + Math.round(price.openPrice*100)/100 + " HIGH:" - + Math.round(price.highPrice*100)/100 + " LOW:" - + Math.round(price.lowPrice*100)/100 + " CLOSE:" - + Math.round(price.closePrice*100)/100 + " VOLUME:" - + price.volume; - } - } - } - - Text { - id:priceAxis - x:25 - y:25 - font.pointSize: 15 - color:"yellow" - opacity: 0.7 - focus: false - } - Text { - id:volumeAxis - x:canvas.width - 200 - y:25 - font.pointSize: 15 - color:"yellow" - opacity: 0.7 - } - - Rectangle { - id:progress - x:canvas.width/2 - 100 - y:canvas.height/2 - width:childrenRect.width - height: childrenRect.height - opacity: 0 - color:"white" - property string text; - Text { - text:parent.text - font.pointSize: 20 - } - } - - Button { - id:runButton - text:"Run this chart" - y:0 - x:canvas.width/2 - 50 - opacity: 0.5 - onClicked: { - if (canvas.running) { - canvas.running = false; - canvas.frames = canvas.first; - canvas.requestPaint(); - text = "Run this chart"; - comment.text = stockModel.description; - } else { - text = " Stop running "; - canvas.runChart(); - } - } - } - Button { - id:returnButton - text:"Stocks" - y:0 - anchors.left : runButton.right - anchors.leftMargin : 20 - opacity: 0.5 - onClicked: { - stockList.opacity = 1; - canvas.opacity = 0; - } - } - PinchArea { - anchors.fill: parent - onPinchUpdated : { - var current = pinch.center; - var scale = pinch.scale; - console.log("center:" + pinch.center + " scale:" + pinch.scale); - //canvas.requestPaint(); - } - } - - MouseArea { - anchors.fill: parent - - onDoubleClicked: { - if (stockModel.dataCycle == StockModel.Daily) - stockModel.dataCycle = StockModel.Weekly; - else if (stockModel.dataCycle == StockModel.Weekly) - stockModel.dataCycle = StockModel.Monthly; - else - stockModel.dataCycle = StockModel.Daily; - } - - onPositionChanged: { - if (mouse.modifiers & Qt.ControlModifier) { - if (canvas.mouseX == 0 && canvas.mouseY == 0) { - canvas.mouseX = mouse.x; - canvas.mouseY = mouse.y; - } - } else{ - var w = (view.width/view.count)*canvas.scaleX; - - //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2); - - var movedX = Math.round((canvas.mousePressedX - mouse.x)/w); - if (movedX != 0 || canvas.movedY != 0) { - if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) { - canvas.first += movedX; - canvas.last += movedX; - } - canvas.requestPaint(); - } - } - } - - onPressed: { - canvas.mousePressedX = mouse.x; - canvas.mousePressedY = mouse.y; - } - - onReleased : { - if (mouse.modifiers & Qt.ControlModifier) { - var sx = mouse.x - canvas.mouseX; - var sy = canvas.mouseY - mouse.y; - - if (Math.abs(sx) < 50) sx = 0; - if (Math.abs(sy) < 50) sy = 0; - - if (sx > 0) - canvas.scaleX *= sx/100 +1; - else - canvas.scaleX *= 1/(-sx/100 + 1); - - if (sy > 0) - canvas.scaleY *= sy/100 +1; - else - canvas.scaleY *= 1/(-sy/100 + 1); - - if (canvas.scaleX < 1) - canvas.scaleX = 1; - - //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY); - - canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX); - canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX); - - canvas.mouseX = 0; - canvas.mouseY = 0; - canvas.mousePressedX = 0; - canvas.mousePressedY = 0; - canvas.requestPaint(); - } - } - } - - function runChart() { - canvas.running = true; - requestPaint(); - } - - function showPriceAt(x) { - var w = (view.width/view.count)*canvas.scaleX; - //header.updateCurrent(stockModel.stockPriceAtIndex(canvas.first + Math.round(x/w))); - //console.log("x:" + x + " w:" + w + " index:" + (canvas.first + Math.round(x/w))); - } - - function drawPrice(ctx, from, to, color, price, points, highest) - { - ctx.globalAlpha = 0.7; - ctx.strokeStyle = color; - ctx.lineWidth = 1; - ctx.beginPath(); - - //price x axis - priceAxis.text = "price:" + Math.round(highest); - ctx.font = "bold 12px sans-serif"; - - ctx.strokeText("price", 25, 25); - for (var j = 1; j < 30; j++) { - var val = (highest * j) / 30; - val = canvas.height * (1 - val/highest); - ctx.beginPath(); - - ctx.moveTo(10, val); - if (j % 5) - ctx.lineTo(15, val); - else - ctx.lineTo(20, val); - ctx.stroke(); - } - - ctx.beginPath(); - ctx.moveTo(10, 0); - ctx.lineTo(10, canvas.height); - ctx.stroke(); - - - var w = canvas.width/points.length; - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var y = points[i][price]; - y += canvas.movedY; - - y = canvas.height * (1 - y/highest); - if (i == 0) { - ctx.moveTo(x+w/2, y); - } else { - ctx.lineTo(x+w/2, y); - } - } - ctx.stroke(); - } - - function drawKLine(ctx, from, to, points, highest) - { - ctx.globalAlpha = 0.4; - ctx.lineWidth = 2; - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var open = canvas.height * (1 - points[i].open/highest) - canvas.movedY; - var close = canvas.height * (1 - points[i].close/highest) - canvas.movedY; - var high = canvas.height * (1 - points[i].high/highest) - canvas.movedY; - var low = canvas.height * (1 - points[i].low/highest) - canvas.movedY; - - var top, bottom; - if (close <= open) { - ctx.fillStyle = Qt.rgba(1, 0, 0, 1); - ctx.strokeStyle = Qt.rgba(1, 0, 0, 1); - top = close; - bottom = open; - } else { - ctx.fillStyle = Qt.rgba(0, 1, 0, 1); - ctx.strokeStyle = Qt.rgba(0, 1, 0, 1); - top = open; - bottom = close; - } - - var w1, w2; - w1 = canvas.width/points.length; - w2 = w1 > 10 ? w1/2 : w1; - - ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top); - ctx.beginPath(); - ctx.moveTo(x+w1/2, high); - ctx.lineTo(x+w1/2, low); - ctx.stroke(); - } - ctx.globalAlpha = 1; - - } - - function drawVolume(ctx, from, to, color, price, points, highest) - { - ctx.fillStyle = color; - ctx.globalAlpha = 0.6; - ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1); - ctx.lineWidth = 1; - - //volume x axis - volumeAxis.text = "volume:" + Math.round(highest/(1000*100)) + "M"; - for (var j = 1; j < 30; j++) { - var val = (highest * j) / 30; - val = canvas.height * (1 - val/highest); - ctx.beginPath(); - if (j % 5) - ctx.moveTo(canvas.width - 15, val); - else - ctx.moveTo(canvas.width - 20, val); - ctx.lineTo(canvas.width - 10, val); - ctx.stroke(); - } - - ctx.beginPath(); - ctx.moveTo(canvas.width - 10, 0); - ctx.lineTo(canvas.width - 10, canvas.height); - ctx.stroke(); - - var end = canvas.running? canvas.frames - canvas.first :points.length; - for (var i = 0; i < end; i++) { - var x = points[i].x; - var y = points[i][price]; - y = canvas.height * (1 - y/highest); - ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y); - } - } -/* - onPainted : { - if (canvas.running) { - if (frames >= last) { - canvas.running = false; - canvas.frames = first; - runButton.text = "Run this chart"; - comment.text = stockModel.description; - requestPaint(); - } else { - frames += Math.round(view.count / 100); - if (frames > last) frames = last; - var price = stockModel.stockPriceAtIndex(frames); - if (price) { - comment.updateCurrent(price); - } - - requestPaint(); - } - } - } -*/ - onPaint: { - if (view.currentIndex <= 0) - first = 0; - if (last >= view.count) - last = view.count - 1; - - //console.log("painting... first:" + first + ", last:" + last + " current:" + view.currentIndex); - var ctx = canvas.getContext("2d"); - ctx.save(); - - ctx.globalCompositeOperation = "source-over"; - ctx.lineWidth = 1; - ctx.lineJoin = "round"; - ctx.fillStyle = "rgba(0,0,0,0)"; - - ctx.fillRect(0, 0, canvas.width, canvas.height); - - - - var highestPrice = 500/canvas.scaleY; - var highestValume = 600 * 1000 * 1000/canvas.scaleY; - var points = []; - for (var i = 0; i <= last - first; i++) { - var price = stockModel.stockPriceAtIndex(i + first); - points.push({ - x: i*canvas.width/(last-first+1), - open: price.openPrice, - close: price.closePrice, - high:price.highPrice, - low:price.lowPrice, - volume:price.volume - }); - } - - drawPrice(ctx, first, last, Qt.rgba(1, 0, 0, 1),"high", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0, 1, 0, 1),"low", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0, 0, 1, 1),"open", points, highestPrice); - drawPrice(ctx, first, last, Qt.rgba(0.5, 0.5, 0.5, 1),"close", points, highestPrice); - drawVolume(ctx, first, last, Qt.rgba(0.3, 0.5, 0.7, 1),"volume", points, highestValume); - drawKLine(ctx, first, last, points, highestPrice); - ctx.restore(); - } - } -} diff --git a/examples/quick/canvas/stockchart/stockchart.pro b/examples/quick/canvas/stockchart/stockchart.pro deleted file mode 100644 index e368746db5..0000000000 --- a/examples/quick/canvas/stockchart/stockchart.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = lib -CONFIG += qt plugin -QT += qml network - -DESTDIR = com/nokia/StockChartExample -TARGET = qmlstockchartexampleplugin - -SOURCES += model.cpp plugin.cpp -HEADERS += model.h -qdeclarativesources.files += \ - com/nokia/StockChartExample/qmldir \ - stock.qml - -qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample - -sources.files += stockchart.pro model.h model.cpp plugin.cpp README -sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins -target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample - -INSTALLS += qdeclarativesources sources target diff --git a/examples/quick/canvas/tiger/tiger.qml b/examples/quick/canvas/tiger/tiger.qml index 2eb1bb2106..6b8e0035a2 100644 --- a/examples/quick/canvas/tiger/tiger.qml +++ b/examples/quick/canvas/tiger/tiger.qml @@ -43,18 +43,18 @@ import "../contents" import "tiger.js" as Tiger Item { id:container - width:360 - height:600 + width:320 + height:480 Column { spacing:5 anchors.fill:parent - Text { font.pointSize:25; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter} + Text { font.pointSize:15; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter} Canvas { id:canvas - width:360 - height:360 + width:320 + height:280 smooth:true renderTarget:Canvas.FramebufferObject renderStrategy: Canvas.Cooperative @@ -115,14 +115,14 @@ Item { } Rectangle { id:controls - width:360 - height:160 + width:320 + height:150 Column { spacing:3 - Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleX"} - Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleY"} - Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"} - Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"} + Slider {id:scaleXCtrl; width:300; height:20; min:0.1; max:10; init:0.5; name:"ScaleX"} + Slider {id:scaleYCtrl; width:300; height:20; min:0.1; max:10; init:0.5; name:"ScaleY"} + Slider {id:rotateCtrl; width:300; height:20; min:0; max:Math.PI*2; init:0; name:"Rotate"} + Slider {id:alphaCtrl; width:300; height:20; min:0; max:1; init:1; name:"Alpha"} } } } diff --git a/examples/quick/canvas/twitterfriends/TwitterUser.qml b/examples/quick/canvas/twitterfriends/TwitterUser.qml deleted file mode 100644 index 8b906216ef..0000000000 --- a/examples/quick/canvas/twitterfriends/TwitterUser.qml +++ /dev/null @@ -1,294 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Item { - id:twitterUser - property variant friends : []; - property string name : ""; - property string twitterId : ""; - property string image : ""; - property string url : ""; - property string desc : ""; - width : 0; - height : 0; - property int posX:0; - property int posY:0; - property bool hasFocus : false; - property variant canvas; - property variant manager; - property variant linkColor; - property bool selected : false; - - Rectangle { - id:twitterStatus - x:twitterUser.width - y:twitterUser.height - width:250 - height:60 - opacity: 0 - border.color:"steelblue" - border.width:3 - Column { - spacing:2 - Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere} - Text {color:"steelblue"; font.pointSize:8; width:250; height:30; text:twitterUser.url; wrapMode: Text.WrapAnywhere} - } - } - - function moved() { - twitterUser.posX = twitterUser.x; - twitterUser.posY = twitterUser.y; - twitterUser.canvas.requestPaint(); - } - - onXChanged: moved(); - onYChanged: moved(); - - MouseArea { - anchors.fill:parent - drag.target : twitterUser - drag.axis : Drag.XandYAxis - - onClicked: { - if (!twitterUser.selected) { - twitterUser.selected = true; - twitterStatus.opacity = 1; - twitterStatus.visible = true; - } else { - twitterUser.selected = false; - twitterStatus.opacity = 0; - } - } - - onDoubleClicked : { - twitterStatus.opacity = 0; - twitterUser.selected = false; - twitterUser.hasFocus = true; - twitterUser.canvas.twitterName = twitterUser.name; - twitterUser.canvas.twitterId = twitterUser.twitterId; - twitterUser.canvas.loading = true; - twitterUser.createFriends(); - } - } - - function show(ctx, layoutChanged) { - var w = canvas.width; - var h = canvas.height; - if (twitterUser.hasFocus) { - twitterUser.width = 60 - twitterUser.height = 60 - twitterUser.posX = w/2; - twitterUser.posY = h/2; - } else { - twitterUser.width = 40 - twitterUser.height = 40 - } - - - if (twitterUser.hasFocus) { - if (layoutChanged) - twitterUser.layoutFriends(); - twitterUser.linkFriends(ctx); - twitterUser.showFriends(ctx); - ctx.shadowOffsetX = 5; - ctx.shadowOffsetY = 5; - ctx.shadowBlur = 7; - ctx.shadowColor = "blue"; - ctx.globalAlpha = 1; - } else { - ctx.shadowOffsetX = 5; - ctx.shadowOffsetY = 5; - ctx.shadowBlur = 7; - ctx.shadowColor = twitterUser.linkColor; - ctx.globalAlpha = 0.6; - } - - if (twitterUser.canvas.isImageLoaded(twitterUser.image)) { - ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height); - } -// ctx.font = "15px"; -// var nameSize = ctx.measureText(twitterUser.name).width; -// ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10); - } - function dump() { - console.log("name:" + twitterUser.name - + " x:" + twitterUser.posX - + " y:" + twitterUser.posY - + " width:" + twitterUser.width - + " height:" + twitterUser.height - + " id:" + twitterUser.twitterId - + " image:" + twitterUser.image - + " url:" + twitterUser.url + "\n" + twitterUser.desc); - } - - function layoutFriends() { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend) { - friend.x = Math.random() *w; - friend.y = Math.random() *h; - } - } - } - - function showFriends(ctx) { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length && i < 15; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { - friend.hasFocus = false; - friend.show(ctx, false); - } - } - } - - function linkFriends(ctx) { - var w = canvas.width; - var h = canvas.height; - for (var i=0; i < twitterUser.friends.length && i < 15; i++) { - var friend = manager.getById(twitterUser.friends[i]); - if (friend && twitterUser.canvas.isImageLoaded(friend.image)) { - if (!friend.linkColor) - friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255 - , ((Math.random() * 200) +55)/255 - , ((Math.random() * 200) +55)/255, 0.8); - ctx.strokeStyle = friend.linkColor; - ctx.lineWidth = 8; - ctx.beginPath(); - ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2); - ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2); - ctx.stroke(); - } - } - } - - - function create(url) { - var x = new XMLHttpRequest; - x.open("GET", url); - - x.onreadystatechange = function() { - if (x.readyState == XMLHttpRequest.DONE) { - var user = eval('(' + x.responseText +')')[0]; - twitterUser.name = user.name; - twitterUser.twitterId = user.id; - twitterUser.image = user.profile_image_url; - twitterUser.canvas.loadImage(twitterUser.image); - twitterUser.url = user.url; - twitterUser.desc = user.description; - twitterUser.createFriends(); - } - } - x.send(); - } - - function createByName(name) { - if (twitterUser.name === "" && twitterUser.twitterId === "") { - twitterUser.name = name; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name; - twitterUser.create(userUrl); - } - } - - function createById(id) { - if (twitterUser.name === "" && twitterUser.twitterId === "") { - twitterUser.twitterId = id; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id; - twitterUser.create(userUrl); - } - } - - function createFriends() { - if (twitterUser.friends.length === 0) { - var x = new XMLHttpRequest; - var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId; - x.open("GET", friendsUrl); - - x.onreadystatechange = function() { - if (x.readyState == XMLHttpRequest.DONE) { - twitterUser.friends = eval('(' + x.responseText +')').ids; - var doRequest = false; - var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id="; - - for (var i=0; i Date: Wed, 14 Mar 2012 12:41:37 +1000 Subject: Reuse a QQuickCanvas in examples auto test. Much faster than creating a new one for each example. Change-Id: Ic32f244047e0dba78134ba0e3d368260be838f1e Reviewed-by: Michael Brasser --- tests/auto/quick/examples/tst_examples.cpp | 36 +++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp index c29da570c3..3c109471c5 100644 --- a/tests/auto/quick/examples/tst_examples.cpp +++ b/tests/auto/quick/examples/tst_examples.cpp @@ -62,6 +62,7 @@ class tst_examples : public QObject Q_OBJECT public: tst_examples(); + ~tst_examples(); private slots: void init(); @@ -81,9 +82,11 @@ private: QStringList findQmlFiles(const QDir &); QQmlEngine engine; + + QQuickCanvas *canvas; }; -tst_examples::tst_examples() +tst_examples::tst_examples() : canvas(0) { // Add files to exclude here excludedFiles << "doc/src/snippets/qml/listmodel.qml"; //Just a ListModel, no root QQuickItem @@ -112,6 +115,11 @@ tst_examples::tst_examples() #endif } +tst_examples::~tst_examples() +{ + delete canvas; +} + void tst_examples::init() { if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets")) @@ -252,13 +260,16 @@ void tst_examples::sgexamples() component.completeCreate(); QVERIFY(root); - QQuickCanvas canvas; - root->setParentItem(canvas.rootItem()); + if (!canvas) { + canvas = new QQuickCanvas(); + canvas->resize(240, 320); + canvas->show(); + QTest::qWaitForWindowShown(canvas); + } + root->setParentItem(canvas->rootItem()); component.completeCreate(); - canvas.show(); - - QTest::qWaitForWindowShown(&canvas); + qApp->processEvents(); } void tst_examples::sgsnippets_data() @@ -293,13 +304,16 @@ void tst_examples::sgsnippets() component.completeCreate(); QVERIFY(root); - QQuickCanvas canvas; - root->setParentItem(canvas.rootItem()); + if (!canvas) { + canvas = new QQuickCanvas(); + canvas->resize(240, 320); + canvas->show(); + QTest::qWaitForWindowShown(canvas); + } + root->setParentItem(canvas->rootItem()); component.completeCreate(); - canvas.show(); - - QTest::qWaitForWindowShown(&canvas); + qApp->processEvents(); } QTEST_MAIN(tst_examples) -- cgit v1.2.3 From eb04ab1081ae29962260514a85bbd88c091cb322 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 9 Mar 2012 11:47:42 +0100 Subject: Remove use of redundante nullPixmap image reference Change-Id: I40b82c25c813722a94d9897e1f2e1dd8a1681762 Reviewed-by: Kim M. Kalland --- src/quick/util/qquickpixmapcache.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 6ebdf57c22..9185fba343 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -984,7 +984,6 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q struct QQuickPixmapNull { QUrl url; - QImage image; QSize size; }; Q_GLOBAL_STATIC(QQuickPixmapNull, nullPixmap); @@ -1087,8 +1086,7 @@ QImage QQuickPixmap::image() const { if (d && d->textureFactory) return d->textureFactory->image(); - else - return nullPixmap()->image; + return QImage(); } void QQuickPixmap::setImage(const QImage &p) -- cgit v1.2.3 From 956399fc36bfa0b6bb4a1523ff2f45d2a6d20aa3 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 8 Mar 2012 23:15:11 +0100 Subject: Fix wrap modes not being set. Change-Id: Id75ae3f01e6ed72b4a754e05bd55d5ed73b56920 Reviewed-by: Kim M. Kalland --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index e605f2ea7e..70fbbab18f 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -5740,7 +5740,7 @@ void QQuickItemLayer::setSize(const QSize &size) void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode) { - if (mode != m_wrapMode) + if (mode == m_wrapMode) return; m_wrapMode = mode; -- cgit v1.2.3 From d73e6d4374e21a4137b1b83fa76cf9600b214a8b Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Wed, 14 Mar 2012 16:07:03 +1000 Subject: Disable particle-related examples from tst_examples CustomParticle and ShaderEffect are currently broken. Disabling these examples until they can be fixed. Task-number: QTBUG-24034 Change-Id: Ic1ebba1f66f28495822cd729af1e1c24acad79da Reviewed-by: Alan Alpert --- tests/auto/quick/examples/tst_examples.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp index 3c109471c5..9a2a800cfd 100644 --- a/tests/auto/quick/examples/tst_examples.cpp +++ b/tests/auto/quick/examples/tst_examples.cpp @@ -113,6 +113,10 @@ tst_examples::tst_examples() : canvas(0) excludedDirs << "demos/flickr"; excludedDirs << "demos/photoviewer"; #endif + + // QTBUG-24034 - don't run customparticle examples + excludedDirs << "demos/flickr"; + excludedDirs << "examples/particles/customparticle"; } tst_examples::~tst_examples() -- cgit v1.2.3 From 4cd2f0bb2ff262bafb09eae23db919714858e4a2 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 14 Mar 2012 15:28:27 +1000 Subject: Fix memory leak with the shared distance field glyph cache. A new glyph node instance registers its owner element with its glyph cache which in the case of the shared distance field glyph cache connects a signal from the cache to a slot on the owner, changing the text creates a new node but destroying the old node didn't remove the connection causing them to accumulate over time. In the glyph node; unregister the owner element from the cache on destruction, and in the cache only connect an owner element the first time it is registered and keep a reference count so the items can be disconnected when registrations from all nodes have been cancelled. Change-Id: Ibf32a146e146dbbf4e0556d1bd756465bd8e45ba Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 1 + .../scenegraph/qsgshareddistancefieldglyphcache.cpp | 19 +++++++++++++++---- .../scenegraph/qsgshareddistancefieldglyphcache_p.h | 12 ++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index 79e5c3b0f4..e049e92bae 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -76,6 +76,7 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode() glyphIndexes.append(m_allGlyphs.at(i).glyphIndex); m_glyph_cache->release(glyphIndexes); m_glyph_cache->unregisterGlyphNode(this); + m_glyph_cache->unregisterOwnerElement(ownerElement()); } for (int i = 0; i < m_nodesToDelete.count(); ++i) diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp index 76fb9036f4..cd5aaaedd7 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp @@ -234,14 +234,25 @@ void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet &glyphs void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement) { - bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess())); - Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot"); - Q_UNUSED(ok); + Owner &owner = m_registeredOwners[ownerElement]; + if (owner.ref == 0) { + owner.item = ownerElement; + + bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess())); + Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot"); + Q_UNUSED(ok); + } + ++owner.ref; } void QSGSharedDistanceFieldGlyphCache::unregisterOwnerElement(QQuickItem *ownerElement) { - disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess())); + QHash::iterator it = m_registeredOwners.find(ownerElement); + if (it != m_registeredOwners.end() && --it->ref <= 0) { + if (it->item) + disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess())); + m_registeredOwners.erase(it); + } } #if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG_) diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h index 4a91b4473a..19844bbda4 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -105,8 +106,19 @@ private: QPoint position; }; + struct Owner + { + Owner() : ref(0) {} + Owner(const Owner &o) : item(o.item), ref(o.ref) {} + Owner &operator =(const Owner &o) { item = o.item; ref = o.ref; return *this; } + + QQmlGuard item; + int ref; + }; + QHash m_pendingReadyGlyphs; QHash m_bufferForGlyph; + QHash m_registeredOwners; }; QT_END_NAMESPACE -- cgit v1.2.3 From b7f3138957ced630aca98ecb63acf873e7d2d103 Mon Sep 17 00:00:00 2001 From: Luis Gabriel Lima Date: Wed, 7 Mar 2012 23:24:18 -0300 Subject: Fix AND expression in v4 The type of the and expressions, e.g. (a && b), were being assigned to the type of the right hand expression (b). As reported in QTBUG-24660, this approach could lead to some unexpected behaviors. Now, when the left and right hand expressions are of different types, the responsability to deal with the and expression is delegated to v8. Task-number: QTBUG-24660 Change-Id: Ic42ebb035e62e2f197c337b2106d00453a99f04c Reviewed-by: Roberto Raggi --- src/qml/qml/v4/qv4irbuilder.cpp | 12 ++- tests/auto/qml/v4/data/logicalAnd.2.qml | 6 ++ tests/auto/qml/v4/data/logicalAnd.3.qml | 8 ++ tests/auto/qml/v4/data/logicalAnd.4.qml | 8 ++ tests/auto/qml/v4/data/logicalAnd.5.qml | 7 ++ tests/auto/qml/v4/data/logicalAnd.6.qml | 9 +++ tests/auto/qml/v4/data/logicalAnd.7.qml | 9 +++ tests/auto/qml/v4/data/logicalAnd.qml | 6 ++ tests/auto/qml/v4/data/nestedLogicalAnd.qml | 14 ++++ tests/auto/qml/v4/tst_v4.cpp | 111 ++++++++++++++++++++++++++++ 10 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 tests/auto/qml/v4/data/logicalAnd.2.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.3.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.4.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.5.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.6.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.7.qml create mode 100644 tests/auto/qml/v4/data/logicalAnd.qml create mode 100644 tests/auto/qml/v4/data/nestedLogicalAnd.qml diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 8f7422454a..06178259f2 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -911,12 +911,15 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) IR::BasicBlock *iffalse = _function->newBasicBlock(); IR::BasicBlock *endif = _function->newBasicBlock(); - condition(ast->left, iftrue, iffalse); + ExprResult left = expression(ast->left); + IR::Temp *cond = _block->TEMP(IR::BoolType); + _block->MOVE(cond, left); + _block->CJUMP(cond, iftrue, iffalse); IR::Temp *r = _block->TEMP(IR::InvalidType); _block = iffalse; - _block->MOVE(r, _block->CONST(IR::BoolType, 0)); // ### use the right null value + _block->MOVE(r, cond); _block->JUMP(endif); _block = iftrue; @@ -924,9 +927,12 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) _block->MOVE(r, right); _block->JUMP(endif); + if (left.type() != right.type()) + discard(); + _block = endif; - r->type = right.type(); // ### not exactly, it can be IR::BoolType. + r->type = right.type(); _expr.code = r; } } break; diff --git a/tests/auto/qml/v4/data/logicalAnd.2.qml b/tests/auto/qml/v4/data/logicalAnd.2.qml new file mode 100644 index 0000000000..cc3d75bd90 --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.2.qml @@ -0,0 +1,6 @@ +import Qt.v4 1.0 + +Result { + property string s: "foo" && "bar" + result: s == "bar" +} diff --git a/tests/auto/qml/v4/data/logicalAnd.3.qml b/tests/auto/qml/v4/data/logicalAnd.3.qml new file mode 100644 index 0000000000..6527f05d07 --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.3.qml @@ -0,0 +1,8 @@ +import Qt.v4 1.0 + +Result { + property string s: "" + property bool flag: true + + result: (s && flag) == "" +} diff --git a/tests/auto/qml/v4/data/logicalAnd.4.qml b/tests/auto/qml/v4/data/logicalAnd.4.qml new file mode 100644 index 0000000000..fbcee91699 --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.4.qml @@ -0,0 +1,8 @@ +import Qt.v4 1.0 + +Result { + property string s: "foo" + property bool flag: true + + result: (!flag && s) == false +} diff --git a/tests/auto/qml/v4/data/logicalAnd.5.qml b/tests/auto/qml/v4/data/logicalAnd.5.qml new file mode 100644 index 0000000000..f0698463fe --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.5.qml @@ -0,0 +1,7 @@ +import Qt.v4 1.0 + +Result { + property bool flag: true + + result: (null && flag) == null +} diff --git a/tests/auto/qml/v4/data/logicalAnd.6.qml b/tests/auto/qml/v4/data/logicalAnd.6.qml new file mode 100644 index 0000000000..e98b5c99cd --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.6.qml @@ -0,0 +1,9 @@ +import Qt.v4 1.0 + +Result { + property string s: "" + property bool flag: true + property string subresult: s && flag + + result: subresult === "" +} diff --git a/tests/auto/qml/v4/data/logicalAnd.7.qml b/tests/auto/qml/v4/data/logicalAnd.7.qml new file mode 100644 index 0000000000..0f19d3fb40 --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.7.qml @@ -0,0 +1,9 @@ +import Qt.v4 1.0 + +Result { + property real nan: Number.NaN + property bool flag: true + property real subresult: nan && flag + + result: isNaN(subresult) +} diff --git a/tests/auto/qml/v4/data/logicalAnd.qml b/tests/auto/qml/v4/data/logicalAnd.qml new file mode 100644 index 0000000000..40fc3616c2 --- /dev/null +++ b/tests/auto/qml/v4/data/logicalAnd.qml @@ -0,0 +1,6 @@ +import Qt.v4 1.0 + +Result { + property int a: 10 + result: a == 10 && a == 2 +} diff --git a/tests/auto/qml/v4/data/nestedLogicalAnd.qml b/tests/auto/qml/v4/data/nestedLogicalAnd.qml new file mode 100644 index 0000000000..1358fcea64 --- /dev/null +++ b/tests/auto/qml/v4/data/nestedLogicalAnd.qml @@ -0,0 +1,14 @@ +import Qt.v4 1.0 + +Result { + property bool val1: false + property bool val2: true + property bool val3: false + + property bool b1: (true && true && false) + property bool b2: (true && (false && true)) + property bool b3: ((true && true) && true) + property bool b4: (val1 && (val2 && val3)) ? true : false + + result: !b1 && !b2 && b3 && !b4 +} diff --git a/tests/auto/qml/v4/tst_v4.cpp b/tests/auto/qml/v4/tst_v4.cpp index 91a32268cf..ed65cd2a82 100644 --- a/tests/auto/qml/v4/tst_v4.cpp +++ b/tests/auto/qml/v4/tst_v4.cpp @@ -64,6 +64,8 @@ private slots: void unnecessaryReeval(); void logicalOr(); void nestedLogicalOr(); + void logicalAnd(); + void nestedLogicalAnd(); void conditionalExpr(); void qtscript(); void qtscript_data(); @@ -208,6 +210,115 @@ void tst_v4::nestedLogicalOr() delete o; } +void tst_v4::logicalAnd() +{ + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 0); + delete o; + } + + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.2.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } + + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.3.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } + + { + // QTBUG-24660 + QQmlComponent component(&engine, testFileUrl("logicalAnd.4.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } + + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.5.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } + + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.6.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } + + { + QQmlComponent component(&engine, testFileUrl("logicalAnd.7.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; + } +} + +void tst_v4::nestedLogicalAnd() +{ + QQmlComponent component(&engine, testFileUrl("nestedLogicalAnd.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + ResultObject *ro = qobject_cast(o); + QVERIFY(ro != 0); + + QCOMPARE(ro->result(), 1); + delete o; +} + void tst_v4::conditionalExpr() { { -- cgit v1.2.3 From c8262855f4b0ff50ac3259904545cb8ac26848c5 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Wed, 14 Mar 2012 09:05:17 +0100 Subject: CodeCoverage: Skip headersclean test. The code coverage tool adds #line when instrumenting the code using the gcc syntax. tst_headersclean uses the -pedantic-errors flag which causes a fatal error when the code is instrumented with the coverage tool. Similar change was done for qtbase (4ee14d6f87688492). Change-Id: I525879ef56463473dd3c9eb91dee4d9b8310cdf9 Reviewed-by: Rohan McGovern --- tests/auto/auto.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 15d88785de..3f5ac6924d 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -6,4 +6,6 @@ SUBDIRS=\ particles \ qmldevtools +testcocoon: SUBDIRS -= headersclean + contains(QT_CONFIG, qmltest): SUBDIRS += qmltest -- cgit v1.2.3 From bfa7648ca452ebaf42bd10c84a2820d977eb770d Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 8 Mar 2012 16:32:05 +0100 Subject: Remove all accessibility updates to allow changes in qtbase. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to integrate pending api changes these are temporarily removed and will return fixed as soon as qtbase is up to date. Change-Id: I558b6049ac3342d41d67441ddfba6821fc370533 Reviewed-by: Jan-Arve Sæther --- src/quick/items/qquickaccessibleattached.cpp | 1 - src/quick/items/qquickaccessibleattached_p.h | 2 -- src/quick/items/qquickitem.cpp | 4 ---- src/quick/items/qquicktextinput.cpp | 9 --------- 4 files changed, 16 deletions(-) diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index fcf62fa910..46f85417d2 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -144,7 +144,6 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) // Enable accessibility for items with accessible content. This also // enables accessibility for the ancestors of souch items. item->d_func()->setAccessibleFlagAndListener(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::ObjectCreated, item)); } QQuickAccessibleAttached::~QQuickAccessibleAttached() diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 4fc6d90bd8..129c3ef240 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -85,7 +85,6 @@ public: if (name != m_name) { m_name = name; emit nameChanged(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::NameChanged, parent())); } } @@ -95,7 +94,6 @@ public: if (m_description != description) { m_description = description; emit descriptionChanged(); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::DescriptionChanged, parent())); } } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 70fbbab18f..2d84b43008 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3018,7 +3018,6 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) void QQuickItem::focusInEvent(QFocusEvent *) { - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this)); } void QQuickItem::focusOutEvent(QFocusEvent *) @@ -3983,9 +3982,6 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible); - if (isAccessible) - QAccessible::updateAccessibility(QAccessibleEvent(effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide, q)); - emit q->visibleChanged(); if (childVisibilityChanged) emit q->visibleChildrenChanged(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index a353d0c91f..0b21d6b169 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -3261,12 +3261,7 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e m_textDirty = (oldText != m_text); bool changed = finishChange(-1, true, edited); -#ifdef QT_NO_ACCESSIBILITY Q_UNUSED(changed) -#else - if (changed) - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextUpdated, q)); -#endif } @@ -3890,10 +3885,6 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged() } } -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::TextCaretMoved, q)); -#endif - return true; } return false; -- cgit v1.2.3 From 39327bbe38d90cc4ec10c9dddc5722169f454d4f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 14 Mar 2012 12:37:09 +0100 Subject: Debugger: Fix autotests on Windows Remove export macro logic for internal classes. Change-Id: I4dfa7f8e7bc9b5086e01e40342bd00812d5966bd Reviewed-by: Aurindam Jana Reviewed-by: Friedemann Kleint --- tests/auto/qml/debugger/shared/qqmldebugclient.h | 4 ++-- tests/auto/qml/debugger/shared/qqmlenginedebug_p.h | 28 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.h b/tests/auto/qml/debugger/shared/qqmldebugclient.h index d3e5cd59a4..1b05e86a64 100644 --- a/tests/auto/qml/debugger/shared/qqmldebugclient.h +++ b/tests/auto/qml/debugger/shared/qqmldebugclient.h @@ -47,7 +47,7 @@ #include class QQmlDebugConnectionPrivate; -class Q_QML_PRIVATE_EXPORT QQmlDebugConnection : public QIODevice +class QQmlDebugConnection : public QIODevice { Q_OBJECT Q_DISABLE_COPY(QQmlDebugConnection) @@ -81,7 +81,7 @@ private: }; class QQmlDebugClientPrivate; -class Q_QML_PRIVATE_EXPORT QQmlDebugClient : public QObject +class QQmlDebugClient : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QQmlDebugClient) diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h b/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h index 70f04d3a19..2ebdebca53 100644 --- a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h +++ b/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h @@ -73,7 +73,7 @@ class QQmlDebugObjectReference; class QQmlDebugFileReference; class QQmlDebugEngineReference; class QQmlEngineDebugPrivate; -class Q_QML_PRIVATE_EXPORT QQmlEngineDebug : public QObject +class QQmlEngineDebug : public QObject { Q_OBJECT public: @@ -121,7 +121,7 @@ private: Q_DECLARE_PRIVATE(QQmlEngineDebug) }; -class Q_QML_PRIVATE_EXPORT QQmlDebugWatch : public QObject +class QQmlDebugWatch : public QObject { Q_OBJECT public: @@ -152,7 +152,7 @@ private: int m_objectDebugId; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugPropertyWatch : public QQmlDebugWatch +class QQmlDebugPropertyWatch : public QQmlDebugWatch { Q_OBJECT public: @@ -165,7 +165,7 @@ private: QString m_name; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugObjectExpressionWatch : public QQmlDebugWatch +class QQmlDebugObjectExpressionWatch : public QQmlDebugWatch { Q_OBJECT public: @@ -180,7 +180,7 @@ private: }; -class Q_QML_PRIVATE_EXPORT QQmlDebugQuery : public QObject +class QQmlDebugQuery : public QObject { Q_OBJECT public: @@ -202,7 +202,7 @@ private: State m_state; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugFileReference +class QQmlDebugFileReference { public: QQmlDebugFileReference(); @@ -223,7 +223,7 @@ private: int m_columnNumber; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugEngineReference +class QQmlDebugEngineReference { public: QQmlDebugEngineReference(); @@ -240,7 +240,7 @@ private: QString m_name; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugObjectReference +class QQmlDebugObjectReference { public: QQmlDebugObjectReference(); @@ -271,7 +271,7 @@ private: QList m_children; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugContextReference +class QQmlDebugContextReference { public: QQmlDebugContextReference(); @@ -292,7 +292,7 @@ private: QList m_contexts; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugPropertyReference +class QQmlDebugPropertyReference { public: QQmlDebugPropertyReference(); @@ -317,7 +317,7 @@ private: }; -class Q_QML_PRIVATE_EXPORT QQmlDebugEnginesQuery : public QQmlDebugQuery +class QQmlDebugEnginesQuery : public QQmlDebugQuery { Q_OBJECT public: @@ -332,7 +332,7 @@ private: QList m_engines; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugRootContextQuery : public QQmlDebugQuery +class QQmlDebugRootContextQuery : public QQmlDebugQuery { Q_OBJECT public: @@ -347,7 +347,7 @@ private: QQmlDebugContextReference m_context; }; -class Q_QML_PRIVATE_EXPORT QQmlDebugObjectQuery : public QQmlDebugQuery +class QQmlDebugObjectQuery : public QQmlDebugQuery { Q_OBJECT public: @@ -363,7 +363,7 @@ private: }; -class Q_QML_PRIVATE_EXPORT QQmlDebugExpressionQuery : public QQmlDebugQuery +class QQmlDebugExpressionQuery : public QQmlDebugQuery { Q_OBJECT public: -- cgit v1.2.3 From 2a000af954cf24c581b9b1d1f7a3b46da1160c43 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 14 Mar 2012 12:31:27 +0100 Subject: fix gl under example to work also on trivial render loop Change-Id: Ieb6c9c9646b557a7cca952472325c33d265c9262 Reviewed-by: Kim M. Kalland --- examples/quick/openglunderqml/squircle.cpp | 3 ++- examples/quick/openglunderqml/squircle.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/quick/openglunderqml/squircle.cpp b/examples/quick/openglunderqml/squircle.cpp index b56f0baaf6..d15295a0ba 100644 --- a/examples/quick/openglunderqml/squircle.cpp +++ b/examples/quick/openglunderqml/squircle.cpp @@ -68,7 +68,6 @@ void Squircle::itemChange(ItemChange change, const ItemChangeData &) } } - void Squircle::paint() { if (!m_program) { @@ -106,6 +105,8 @@ void Squircle::paint() m_program->setAttributeArray(0, GL_FLOAT, values, 2); m_program->setUniformValue("t", (float) m_t); + glViewport(0, 0, canvas()->width(), canvas()->height()); + glDisable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); diff --git a/examples/quick/openglunderqml/squircle.h b/examples/quick/openglunderqml/squircle.h index 283131a662..9e7a03b75b 100644 --- a/examples/quick/openglunderqml/squircle.h +++ b/examples/quick/openglunderqml/squircle.h @@ -55,7 +55,7 @@ public: Squircle(); qreal t() const { return m_t; } - void setT(qreal t) { m_t = t; emit tChanged(); } + void setT(qreal t) { m_t = t; emit tChanged(); update(); } void itemChange(ItemChange change, const ItemChangeData &); -- cgit v1.2.3 From d6c666f73f03d21c658fa7b8435430a2874f9bc6 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 14 Mar 2012 13:21:59 +0100 Subject: Debugger: Fix autotest for shadow builds Change-Id: I1b53afeb2a9f0d6e571c5ed87304e85896523488 Reviewed-by: Aurindam Jana --- tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp | 2 +- tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp index def704060c..e30b847139 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp @@ -141,7 +141,7 @@ void tst_QQmlInspector::cleanupTestCase() void tst_QQmlInspector::init() { - const QString executable = SRCDIR"/app/app"; + const QString executable = "app/app"; const QString argument = "-qmljsdebugger=port:"STR_PORT",block"; m_process = new QQmlDebugProcess(executable); diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro index c24accac1a..b4ca60b547 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro @@ -7,7 +7,6 @@ SOURCES += tst_qqmlinspector.cpp INCLUDEPATH += ../shared include(../shared/debugutil.pri) -DEFINES += SRCDIR=\\\"$$PWD\\\" CONFIG += parallel_test declarative_debug QT += qml-private testlib -- cgit v1.2.3 From e1d688a23707b2c093294eea365bdf0d087b3f3c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 8 Mar 2012 15:15:10 +0100 Subject: Debugger: Print informational messages via qDebug This allows users to use QT_FATAL_WARNINGS. Change-Id: I114825764c841030418c956d23575159157dfd69 Reviewed-by: Roberto Raggi --- src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp | 2 +- src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp | 2 +- src/qml/debugger/qqmldebugserver.cpp | 2 +- src/qml/qml/qqmlengine.cpp | 2 +- tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp | 6 +++--- tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp | 4 ++-- .../debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp index fb18231b94..7d120cacb0 100644 --- a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp +++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp @@ -132,7 +132,7 @@ void QmlOstPlugin::setPort(int port, bool block) } d->protocol = new QPacketProtocol(d->ost, this); QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - qWarning("QML Debugger: Waiting for connection via OST."); // This message is part of the signalling - do not change the format! + qDebug("QML Debugger: Waiting for connection via OST."); // This message is part of the signalling - do not change the format! } void QmlOstPlugin::readyRead() diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp index 2b12f297e4..4eccd0dd55 100644 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp @@ -147,7 +147,7 @@ void QTcpServerConnection::listen() d->tcpServer = new QTcpServer(this); QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QML Debugger: Waiting for connection on port %d...", d->port); + qDebug("QML Debugger: Waiting for connection on port %d...", d->port); else qWarning("QML Debugger: Unable to listen to port %d.", d->port); } diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp index 23b69af92b..ec3f9dafc2 100644 --- a/src/qml/debugger/qqmldebugserver.cpp +++ b/src/qml/debugger/qqmldebugserver.cpp @@ -389,7 +389,7 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message) iter.value()->stateChanged(newState); } - qWarning("QML Debugger: Connection established."); + qDebug("QML Debugger: Connection established."); d->messageArrivedCondition.wakeAll(); } else if (op == 1) { diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 6f832c2b27..0c8ff6ae27 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1037,7 +1037,7 @@ QQmlDebuggingEnabler::QQmlDebuggingEnabler() { #ifndef QQML_NO_DEBUG_PROTOCOL if (!QQmlEnginePrivate::qml_debugging_enabled) { - qWarning("QML debugging is enabled. Only use this in a safe environment."); + qDebug("QML debugging is enabled. Only use this in a safe environment."); } QQmlEnginePrivate::qml_debugging_enabled = true; #endif diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp index 9377ef6a8f..1682913bc3 100644 --- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp +++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp @@ -72,7 +72,7 @@ private slots: void tst_QQmlDebugClient::initTestCase() { const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT); - QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData()); + QTest::ignoreMessage(QtDebugMsg, waitingMsg.toAscii().constData()); new QQmlEngine(this); m_conn = new QQmlDebugConnection(this); @@ -80,7 +80,7 @@ void tst_QQmlDebugClient::initTestCase() QQmlDebugTestClient client("tst_QQmlDebugClient::handshake()", m_conn); QQmlDebugTestService service("tst_QQmlDebugClient::handshake()"); - QTest::ignoreMessage(QtWarningMsg, "QML Debugger: Connection established."); + QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established."); for (int i = 0; i < 50; ++i) { // try for 5 seconds ... m_conn->connectToHost("127.0.0.1", PORT); @@ -172,7 +172,7 @@ void tst_QQmlDebugClient::sequentialConnect() QTest::qWait(100); connection2.connectToHost("127.0.0.1", PORT); - QTest::ignoreMessage(QtWarningMsg, "QML Debugger: Connection established."); + QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established."); QVERIFY(connection2.waitForConnected()); QVERIFY(connection2.isConnected()); QTRY_VERIFY(client2.state() == QQmlDebugClient::Enabled); diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp index a7fc284443..6e14c03a4c 100644 --- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp +++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp @@ -77,13 +77,13 @@ private slots: void tst_QQmlDebugService::initTestCase() { const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT); - QTest::ignoreMessage(QtWarningMsg, waitingMsg.toAscii().constData()); + QTest::ignoreMessage(QtDebugMsg, waitingMsg.toAscii().constData()); new QQmlEngine(this); m_conn = new QQmlDebugConnection(this); - QTest::ignoreMessage(QtWarningMsg, "QML Debugger: Connection established."); + QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established."); for (int i = 0; i < 50; ++i) { // try for 5 seconds ... m_conn->connectToHost("127.0.0.1", PORT); diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index a35aafff4d..9756313905 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -301,7 +301,7 @@ void tst_QQmlEngineDebugService::initTestCase() qRegisterMetaType(); qmlRegisterType("Test", 1, 0, "NonScriptPropertyElement"); - QTest::ignoreMessage(QtWarningMsg, "QML Debugger: Waiting for connection on port 3768..."); + QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Waiting for connection on port 3768..."); m_engine = new QQmlEngine(this); QList qml; @@ -386,7 +386,7 @@ void tst_QQmlEngineDebugService::initTestCase() m_conn = new QQmlDebugConnection(this); m_conn->connectToHost("127.0.0.1", 3768); - QTest::ignoreMessage(QtWarningMsg, "QML Debugger: Connection established."); + QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established."); bool ok = m_conn->waitForConnected(); QVERIFY(ok); QTRY_VERIFY(QQmlDebugService::hasDebuggingClient()); -- cgit v1.2.3 From a06936e5037c017248a9eefa9378cebfd6b2f5c1 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 2 Mar 2012 17:43:44 +1000 Subject: Don't store duplicate glyph data in a distance field node. This saves at least 16 bytes per character and removes the need to copy data between representations. Change-Id: Ia8236207bdc4ed8292f7b4c72093ee02d13c0463 Reviewed-by: Yoann Lopes --- src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 66 ++++++++++------------ src/quick/scenegraph/qsgdistancefieldglyphnode_p.h | 5 +- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index e049e92bae..a86e663755 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -71,10 +71,7 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode() delete m_material; if (m_glyph_cache) { - QVector glyphIndexes; - for (int i = 0; i < m_allGlyphs.count(); ++i) - glyphIndexes.append(m_allGlyphs.at(i).glyphIndex); - m_glyph_cache->release(glyphIndexes); + m_glyph_cache->release(m_glyphs.glyphIndexes()); m_glyph_cache->unregisterGlyphNode(this); m_glyph_cache->unregisterOwnerElement(ownerElement()); } @@ -123,15 +120,9 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR } m_glyph_cache->populate(glyphs.glyphIndexes()); - const QVector &glyphIndexes = m_glyphs.glyphIndexes(); - const QVector &glyphPositions = m_glyphs.positions(); - for (int i = 0; i < glyphIndexes.count(); ++i) { - GlyphInfo gi; - gi.glyphIndex = glyphIndexes.at(i); - gi.position = glyphPositions.at(i); - m_allGlyphs.append(gi); - m_allGlyphIndexesLookup.insert(gi.glyphIndex); - } + const QVector glyphIndexes = m_glyphs.glyphIndexes(); + for (int i = 0; i < glyphIndexes.count(); ++i) + m_allGlyphIndexesLookup.insert(glyphIndexes.at(i)); m_dirtyGeometry = true; m_dirtyMaterial = true; @@ -205,34 +196,43 @@ void QSGDistanceFieldGlyphNode::updateGeometry() Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT); - QHash > glyphsInOtherTextures; + QHash glyphsInOtherTextures; + + const QVector indexes = m_glyphs.glyphIndexes(); + const QVector positions = m_glyphs.positions(); QVector vp; - vp.reserve(m_allGlyphs.size() * 4); + vp.reserve(indexes.size() * 4); QVector ip; - ip.reserve(m_allGlyphs.size() * 6); + ip.reserve(indexes.size() * 6); QPointF margins(2, 2); QPointF texMargins = margins / m_glyph_cache->fontScale(); - for (int i = 0; i < m_allGlyphs.size(); ++i) { - GlyphInfo glyphInfo = m_allGlyphs.at(i); - QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphInfo.glyphIndex); + + for (int i = 0; i < indexes.size(); ++i) { + const int glyphIndex = indexes.at(i); + QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex); if (c.isNull()) continue; - const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphInfo.glyphIndex); + const QPointF position = positions.at(i); + + const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex); if (texture->textureId && !m_texture) m_texture = texture; if (m_texture != texture) { - if (texture->textureId) - glyphsInOtherTextures[texture].append(glyphInfo); + if (texture->textureId) { + GlyphInfo &glyphInfo = glyphsInOtherTextures[texture]; + glyphInfo.indexes.append(glyphIndex); + glyphInfo.positions.append(position); + } continue; } - QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphInfo.glyphIndex); + QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex); if (!metrics.isNull() && !c.isNull()) { metrics.width += margins.x() * 2; @@ -245,8 +245,8 @@ void QSGDistanceFieldGlyphNode::updateGeometry() c.height += texMargins.y() * 2; } - qreal x = glyphInfo.position.x() + metrics.baselineX + m_position.x(); - qreal y = glyphInfo.position.y() - metrics.baselineY + m_position.y(); + qreal x = position.x() + metrics.baselineX + m_position.x(); + qreal y = position.y() - metrics.baselineY + m_position.y(); m_boundingRect |= QRectF(x, y, metrics.width, metrics.height); @@ -261,7 +261,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry() float ty2 = ty1 + c.height; if (m_baseLine.isNull()) - m_baseLine = glyphInfo.position; + m_baseLine = position; int o = vp.size(); @@ -286,7 +286,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry() ip.append(o + 0); } - QHash >::const_iterator ite = glyphsInOtherTextures.constBegin(); + QHash::const_iterator ite = glyphsInOtherTextures.constBegin(); while (ite != glyphsInOtherTextures.constEnd()) { QHash::iterator subIt = m_subNodes.find(ite.key()); if (subIt == m_subNodes.end()) { @@ -300,17 +300,9 @@ void QSGDistanceFieldGlyphNode::updateGeometry() subIt = m_subNodes.insert(ite.key(), subNode); } - QVector glyphIndexes; - QVector positions; - const QList &subNodeGlyphs = ite.value(); - for (int i = 0; i < subNodeGlyphs.count(); ++i) { - const GlyphInfo &info = subNodeGlyphs.at(i); - glyphIndexes.append(info.glyphIndex); - positions.append(info.position); - } QGlyphRun subNodeGlyphRun(m_glyphs); - subNodeGlyphRun.setGlyphIndexes(glyphIndexes); - subNodeGlyphRun.setPositions(positions); + subNodeGlyphRun.setGlyphIndexes(ite->indexes); + subNodeGlyphRun.setPositions(ite->positions); subIt.value()->setGlyphs(m_originalPosition, subNodeGlyphRun); subIt.value()->update(); diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h index 65ac2d499c..9406ee1bc8 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h @@ -96,11 +96,10 @@ private: QList m_nodesToDelete; struct GlyphInfo { - quint32 glyphIndex; - QPointF position; + QVector indexes; + QVector positions; }; QSet m_allGlyphIndexesLookup; - QList m_allGlyphs; uint m_dirtyGeometry: 1; uint m_dirtyMaterial: 1; -- cgit v1.2.3 From f91dba12746bb1675bfe3a483288e712a867dd7c Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 14 Mar 2012 12:51:22 +0100 Subject: Use the same ReferenceError message wording as V8 Instead of "Can't find variable: foo", use "foo is not defined". This is in preparation of letting V8 throw the exception when a property lookup fails on the QML scope object (needed for QTBUG-24448). Change-Id: I3c747482a8ef138dad9a85530a4f6b5c4c818a03 Reviewed-by: Aaron Kennedy --- src/qml/qml/v8/qv8contextwrapper.cpp | 4 +-- tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp | 2 +- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 38 +++++++++++----------- .../qquickworkerscript/tst_qquickworkerscript.cpp | 2 +- .../tst_qquickvisualdatamodel.cpp | 12 +++---- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp index 246b716aa0..e7c26fde9e 100644 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ b/src/qml/qml/v8/qv8contextwrapper.cpp @@ -245,7 +245,7 @@ v8::Handle QV8ContextWrapper::NullGetter(v8::Local proper QV8Engine *engine = resource->engine; - QString error = QLatin1String("Can't find variable: ") + engine->toString(property); + QString error = engine->toString(property) + QLatin1String(" is not defined"); v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error))); return v8::Undefined(); } @@ -365,7 +365,7 @@ v8::Handle QV8ContextWrapper::Getter(v8::Local property, expressionContext->unresolvedNames = true; - QString error = QLatin1String("Can't find variable: ") + engine->toString(property); + QString error = engine->toString(property) + QLatin1String(" is not defined"); v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error))); return v8::Undefined(); } diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index 6125362365..6525bde9b8 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -617,7 +617,7 @@ void tst_qqmlcontext::refreshExpressionsRootContext() QQmlContext context(engine.rootContext()); QQmlContext context2(engine.rootContext()); - QString warning = component2.url().toString() + QLatin1String(":4: ReferenceError: Can't find variable: unresolvedName"); + QString warning = component2.url().toString() + QLatin1String(":4: ReferenceError: unresolvedName is not defined"); QObject *o1 = component.create(&context); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 0631df1759..3fe0a2bd1a 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -1416,10 +1416,10 @@ void tst_qqmlecmascript::scriptErrors() QString url = component.url().toString(); QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\""; - QString warning2 = url + ":5: ReferenceError: Can't find variable: a"; + QString warning2 = url + ":5: ReferenceError: a is not defined"; QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\""; - QString warning4 = url + ":13: ReferenceError: Can't find variable: a"; - QString warning5 = url + ":11: ReferenceError: Can't find variable: a"; + QString warning4 = url + ":13: ReferenceError: a is not defined"; + QString warning5 = url + ":11: ReferenceError: a is not defined"; QString warning6 = url + ":10: Unable to assign [undefined] to int"; QString warning7 = url + ":15: Error: Cannot assign to read-only property \"trueProperty\""; QString warning8 = url + ":16: Error: Cannot assign to non-existent property \"fakeProperty\""; @@ -3216,7 +3216,7 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("javascript imports in an import should be private to the import scope") << testFileUrl("jsimportfail/failTwo.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs"))) + << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: ImportOneJs is not defined"))) << (QStringList() << QLatin1String("importScriptFunctionValue")) << (QVariantList() << QVariant(QString())); @@ -3230,14 +3230,14 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("typenames in an import should be private to the import scope") << testFileUrl("jsimportfail/failFour.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest"))) + << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: JsQtTest is not defined"))) << (QStringList() << QLatin1String("importedModuleEnumValue")) << (QVariantList() << QVariant(0)); QTest::newRow("import with imports has it's own activation scope") << testFileUrl("jsimportfail/failFive.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component"))) + << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Component is not defined"))) << (QStringList() << QLatin1String("componentError")) << (QVariantList() << QVariant(0)); @@ -3251,7 +3251,7 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("pragma library imports shouldn't inherit parent imports or scope") << testFileUrl("jsimportfail/testImportPragmaLibrary.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component"))) + << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Component is not defined"))) << (QStringList() << QLatin1String("testValue")) << (QVariantList() << QVariant(0)); @@ -5378,7 +5378,7 @@ void tst_qqmlecmascript::typeOf() // These warnings should not happen once QTBUG-21864 is fixed QString warning1 = component.url().toString() + QLatin1String(":16: Error: Cannot assign [undefined] to QString"); - QString warning2 = component.url().resolved(QUrl("typeOf.js")).toString() + QLatin1String(":1: ReferenceError: Can't find variable: a"); + QString warning2 = component.url().resolved(QUrl("typeOf.js")).toString() + QLatin1String(":1: ReferenceError: a is not defined"); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); @@ -5550,9 +5550,9 @@ void tst_qqmlecmascript::revisionErrors() QQmlComponent component(&engine, testFileUrl("metaobjectRevisionErrors.qml")); QString url = component.url().toString(); - QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; - QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2"; - QString warning3 = url + ":13: ReferenceError: Can't find variable: method2"; + QString warning1 = url + ":8: ReferenceError: prop2 is not defined"; + QString warning2 = url + ":11: ReferenceError: prop2 is not defined"; + QString warning3 = url + ":13: ReferenceError: method2 is not defined"; QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); @@ -5568,11 +5568,11 @@ void tst_qqmlecmascript::revisionErrors() // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 // method2, prop2 from MyRevisionedClass not available // method4, prop4 from MyRevisionedSubclass not available - QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; - QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2"; - QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4"; - QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4"; - QString warning5 = url + ":20: ReferenceError: Can't find variable: method2"; + QString warning1 = url + ":8: ReferenceError: prop2 is not defined"; + QString warning2 = url + ":14: ReferenceError: prop2 is not defined"; + QString warning3 = url + ":10: ReferenceError: prop4 is not defined"; + QString warning4 = url + ":16: ReferenceError: prop4 is not defined"; + QString warning5 = url + ":20: ReferenceError: method2 is not defined"; QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); @@ -5589,9 +5589,9 @@ void tst_qqmlecmascript::revisionErrors() // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1 - QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD"; - QString warning2 = url + ":10: ReferenceError: Can't find variable: propD"; - QString warning3 = url + ":20: ReferenceError: Can't find variable: propD"; + QString warning1 = url + ":30: ReferenceError: methodD is not defined"; + QString warning2 = url + ":10: ReferenceError: propD is not defined"; + QString warning3 = url + ":20: ReferenceError: propD is not defined"; QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp index 6569b877fe..2eadc461cf 100644 --- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp +++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp @@ -275,7 +275,7 @@ void tst_QQuickWorkerScript::scriptError_onCall() QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value))); QTRY_COMPARE(qquickworkerscript_lastWarning, - testFileUrl("script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: Can't find variable: getData")); + testFileUrl("script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: getData is not defined")); qInstallMsgHandler(previousMsgHandler); qApp->processEvents(); diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index dbfd4919b9..73a35c1c78 100644 --- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -612,12 +612,12 @@ void tst_qquickvisualdatamodel::modelProperties() QUrl source(testFileUrl("modelproperties2.qml")); //3 items, 3 i each - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData"); - QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); + QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: modelData is not defined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined"); -- cgit v1.2.3 From dfe32bec2d2397b8f52f5ec54bf3c69f086eadea Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 14 Mar 2012 16:52:35 +0200 Subject: Windows: Mark several declarative test cases insignificant These tests are marked insignificant for now to make CI runs pass. Insignifications need to be removed once the related issues are fixed. Change-Id: I3a1d36e5b17cf2f1b2f00b20b615359d96975f2b Reviewed-by: Friedemann Kleint --- tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro | 2 ++ tests/auto/quick/qquickfontloader/qquickfontloader.pro | 2 ++ tests/auto/quick/qquickitemlayer/qquickitemlayer.pro | 8 +------- tests/auto/quick/qquicktext/qquicktext.pro | 2 ++ tests/auto/quick/qquicktextinput/qquicktextinput.pro | 2 ++ 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro index 2726e20577..68c0d79f92 100644 --- a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro +++ b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro @@ -10,3 +10,5 @@ TESTDATA = data/* CONFIG += parallel_test QT += core-private gui-private qml-private testlib + +win32:CONFIG += insignificant_test # QTBUG-24777 diff --git a/tests/auto/quick/qquickfontloader/qquickfontloader.pro b/tests/auto/quick/qquickfontloader/qquickfontloader.pro index 2eeb286e61..3e52b6fe7b 100644 --- a/tests/auto/quick/qquickfontloader/qquickfontloader.pro +++ b/tests/auto/quick/qquickfontloader/qquickfontloader.pro @@ -13,3 +13,5 @@ TESTDATA = data/* CONFIG += parallel_test QT += core-private gui-private qml-private quick-private network testlib + +win32:CONFIG += insignificant_test # QTBUG-24782 diff --git a/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro b/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro index 9ffdbe7454..20fddb9410 100644 --- a/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro +++ b/tests/auto/quick/qquickitemlayer/qquickitemlayer.pro @@ -27,10 +27,4 @@ OTHER_FILES += \ data/ItemEffect.qml \ data/RectangleEffect.qml - - - - - - - +win32:CONFIG += insignificant_test # QTBUG-24787 diff --git a/tests/auto/quick/qquicktext/qquicktext.pro b/tests/auto/quick/qquicktext/qquicktext.pro index 8932664fa3..daa7bed97b 100644 --- a/tests/auto/quick/qquicktext/qquicktext.pro +++ b/tests/auto/quick/qquicktext/qquicktext.pro @@ -15,3 +15,5 @@ TESTDATA = data/* CONFIG += parallel_test QT += core-private gui-private v8-private qml-private quick-private network testlib + +win32:CONFIG += insignificant_test # QTBUG-24789 diff --git a/tests/auto/quick/qquicktextinput/qquicktextinput.pro b/tests/auto/quick/qquicktextinput/qquicktextinput.pro index 13b087eef5..336338f500 100644 --- a/tests/auto/quick/qquicktextinput/qquicktextinput.pro +++ b/tests/auto/quick/qquicktextinput/qquicktextinput.pro @@ -9,3 +9,5 @@ include (../../shared/util.pri) TESTDATA = data/* QT += core-private gui-private v8-private qml-private quick-private testlib + +win32:CONFIG += insignificant_test # QTBUG-24790 -- cgit v1.2.3 From 8f077f28c51c24e71d95c4e99d322734578d9c9c Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 14 Mar 2012 16:56:22 +0200 Subject: Remove warning about missing file from parserstress test There is no dummy.qml, so trying to find it will cause a warning and return an empty string. Since the url is optional anyway and apparently not relevant to this test, just use empty QUrl directly. Change-Id: I11ba742dedccd6bdea226f680aa57c957afc7dc7 Reviewed-by: Friedemann Kleint --- tests/auto/qml/parserstress/tst_parserstress.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/qml/parserstress/tst_parserstress.cpp b/tests/auto/qml/parserstress/tst_parserstress.cpp index a179a24f5f..eb477af521 100644 --- a/tests/auto/qml/parserstress/tst_parserstress.cpp +++ b/tests/auto/qml/parserstress/tst_parserstress.cpp @@ -128,8 +128,7 @@ void tst_parserstress::ecmascript() QQmlComponent component(&engine); - QString dummyFile = QFINDTESTDATA("dummy.qml"); - component.setData(qmlData, QUrl::fromLocalFile(dummyFile)); + component.setData(qmlData, QUrl()); QFileInfo info(file); -- cgit v1.2.3 From a27fd584df0ec3d1d072501d8fefe576a97a2e53 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 14 Mar 2012 13:39:31 +0100 Subject: Let V8 throw the exception when QML property lookup fails Only V8 knows whether a failed property lookup should actually cause a ReferenceError to be thrown. When evaluating a "typeof" expression, for example, a ReferenceError should not be thrown even if the expression involves global variables that don't exist, according to the ECMA-262 specification. QML should try to match the standard JavaScript behavior. This is achieved by simply returning an empty value handle (to signify the absence of the property), and leaving it to V8 to throw an exception as appropriate. Task-number: QTBUG-21864 Task-number: QTBUG-24448 Change-Id: I9945adcab98fc3b801371163367473d6af0ab31a Reviewed-by: Aaron Kennedy --- src/qml/qml/v8/qv8contextwrapper.cpp | 18 ++++++------------ tests/auto/qml/qqmlecmascript/data/qtbug_24448.js | 6 ++++++ tests/auto/qml/qqmlecmascript/data/qtbug_24448.qml | 7 +++++++ tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 17 +++++++++-------- 4 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 tests/auto/qml/qqmlecmascript/data/qtbug_24448.js create mode 100644 tests/auto/qml/qqmlecmascript/data/qtbug_24448.qml diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp index e7c26fde9e..39392b8984 100644 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ b/src/qml/qml/v8/qv8contextwrapper.cpp @@ -238,16 +238,11 @@ QQmlContextData *QV8ContextWrapper::context(v8::Handle value) return r?r->getContext():0; } -v8::Handle QV8ContextWrapper::NullGetter(v8::Local property, - const v8::AccessorInfo &info) +v8::Handle QV8ContextWrapper::NullGetter(v8::Local, + const v8::AccessorInfo &) { - QV8ContextResource *resource = v8_resource_check(info.This()); - - QV8Engine *engine = resource->engine; - - QString error = engine->toString(property) + QLatin1String(" is not defined"); - v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error))); - return v8::Undefined(); + // V8 will throw a ReferenceError if appropriate ("typeof" should not throw) + return v8::Handle(); } v8::Handle QV8ContextWrapper::Getter(v8::Local property, @@ -365,9 +360,8 @@ v8::Handle QV8ContextWrapper::Getter(v8::Local property, expressionContext->unresolvedNames = true; - QString error = engine->toString(property) + QLatin1String(" is not defined"); - v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error))); - return v8::Undefined(); + // V8 will throw a ReferenceError if appropriate ("typeof" should not throw) + return v8::Handle(); } v8::Handle QV8ContextWrapper::NullSetter(v8::Local property, diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_24448.js b/tests/auto/qml/qqmlecmascript/data/qtbug_24448.js new file mode 100644 index 0000000000..eefe00337c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_24448.js @@ -0,0 +1,6 @@ +var test = false; +try { + eval(foo); +} catch (e) { + test = (typeof foo) === "undefined"; +} diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_24448.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_24448.qml new file mode 100644 index 0000000000..d8d305d104 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_24448.qml @@ -0,0 +1,7 @@ +import "qtbug_24448.js" as Test +import QtQuick 2.0 + +QtObject { + property bool test: Test.test +} + diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 3fe0a2bd1a..8fea635b68 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -207,6 +207,7 @@ private slots: void deleteLater(); void in(); void typeOf(); + void qtbug_24448(); void sharedAttachedObject(); void objectName(); void writeRemovesBinding(); @@ -5376,17 +5377,9 @@ void tst_qqmlecmascript::typeOf() { QQmlComponent component(&engine, testFileUrl("typeOf.qml")); - // These warnings should not happen once QTBUG-21864 is fixed - QString warning1 = component.url().toString() + QLatin1String(":16: Error: Cannot assign [undefined] to QString"); - QString warning2 = component.url().resolved(QUrl("typeOf.js")).toString() + QLatin1String(":1: ReferenceError: a is not defined"); - - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); - QObject *o = component.create(); QVERIFY(o != 0); - QEXPECT_FAIL("", "QTBUG-21864", Abort); QCOMPARE(o->property("test1").toString(), QLatin1String("undefined")); QCOMPARE(o->property("test2").toString(), QLatin1String("object")); QCOMPARE(o->property("test3").toString(), QLatin1String("number")); @@ -5400,6 +5393,14 @@ void tst_qqmlecmascript::typeOf() delete o; } +void tst_qqmlecmascript::qtbug_24448() +{ + QQmlComponent component(&engine, testFileUrl("qtbug_24448.qml")); + QScopedPointer o(component.create()); + QVERIFY(o != 0); + QVERIFY(o->property("test").toBool()); +} + void tst_qqmlecmascript::sharedAttachedObject() { QQmlComponent component(&engine, testFileUrl("sharedAttachedObject.qml")); -- cgit v1.2.3 From b06108350b1390b51886474628e03e2e84640548 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Fri, 27 Jan 2012 11:33:37 +1000 Subject: Ensure that dynamic property storing QObject ptr notifies on delete Previously, when a QObject ptr was stored in a dynamic variant property, the value of the property could change (to a zero ptr) if the QObject was deleted without a notify signal being emitted by the QDeclarativeVMEMetaObject which stores the property. This commit ensures that such a notify signal is emitted correctly. Task-number: QTBUG-23451 Change-Id: I5689abd984b177737f8d5f18950838b73ebde328 Reviewed-by: Martin Jones --- src/qml/qml/qqmlvmemetaobject.cpp | 42 ++++++++++++++++------ src/qml/qml/qqmlvmemetaobject_p.h | 14 ++++++++ src/qml/qml/v8/qv8qobjectwrapper.cpp | 2 +- .../qml/qqmlecmascript/data/dynamicDeletion.3.qml | 30 ++++++++++++++++ .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 22 ++++++++++++ 5 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 tests/auto/qml/qqmlecmascript/data/dynamicDeletion.3.qml diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 7ea89a4a2d..ecfde203c6 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -56,6 +56,28 @@ Q_DECLARE_METATYPE(QJSValue); QT_BEGIN_NAMESPACE +QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr() + : QQmlGuard(0), m_target(0), m_index(-1) +{ +} + +QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr() +{ +} + +void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) +{ + if (m_target && m_index >= 0) + m_target->activate(m_target->object, m_target->methodOffset + m_index, 0); +} + +void QQmlVMEVariantQObjectPtr::setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index) +{ + m_target = target; + m_index = index; + setObject(obj); +} + class QQmlVMEVariant { public: @@ -79,7 +101,7 @@ public: inline const QDateTime &asQDateTime(); inline const QJSValue &asQJSValue(); - inline void setValue(QObject *); + inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index); inline void setValue(const QVariant &); inline void setValue(int); inline void setValue(bool); @@ -93,7 +115,7 @@ public: inline void setValue(const QJSValue &); private: int type; - void *data[4]; // Large enough to hold all types + void *data[6]; // Large enough to hold all types inline void cleanup(); }; @@ -127,7 +149,7 @@ void QQmlVMEVariant::cleanup() type == QMetaType::Double) { type = QVariant::Invalid; } else if (type == QMetaType::QObjectStar) { - ((QQmlGuard*)dataPtr())->~QQmlGuard(); + ((QQmlVMEVariantQObjectPtr*)dataPtr())->~QQmlVMEVariantQObjectPtr(); type = QVariant::Invalid; } else if (type == QMetaType::QString) { ((QString *)dataPtr())->~QString(); @@ -174,8 +196,8 @@ void *QQmlVMEVariant::dataPtr() QObject *QQmlVMEVariant::asQObject() { - if (type != QMetaType::QObjectStar) - setValue((QObject *)0); + if (type != QMetaType::QObjectStar) + setValue((QObject *)0, 0, -1); return *(QQmlGuard *)(dataPtr()); } @@ -268,14 +290,14 @@ const QJSValue &QQmlVMEVariant::asQJSValue() return *(QJSValue *)(dataPtr()); } -void QQmlVMEVariant::setValue(QObject *v) +void QQmlVMEVariant::setValue(QObject *v, QQmlVMEMetaObject *target, int index) { if (type != QMetaType::QObjectStar) { cleanup(); type = QMetaType::QObjectStar; - new (dataPtr()) QQmlGuard(); + new (dataPtr()) QQmlVMEVariantQObjectPtr; } - *(QQmlGuard*)(dataPtr()) = v; + reinterpret_cast(dataPtr())->setGuardedValue(v, target, index); } void QQmlVMEVariant::setValue(const QVariant &v) @@ -629,7 +651,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) break; case QMetaType::QObjectStar: needActivate = *reinterpret_cast(a[0]) != data[id].asQObject(); - data[id].setValue(*reinterpret_cast(a[0])); + data[id].setValue(*reinterpret_cast(a[0]), this, id); break; case QMetaType::QVariant: writeProperty(id, *reinterpret_cast(a[0])); @@ -892,7 +914,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) if (value.userType() == QMetaType::QObjectStar) { QObject *o = qvariant_cast(value); needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o); - data[id].setValue(qvariant_cast(value)); + data[id].setValue(qvariant_cast(value), this, id); } else { needActivate = (data[id].dataType() != qMetaTypeId() || data[id].asQVariant().userType() != value.userType() || diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index deee989383..84c88fdd7b 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -136,6 +136,19 @@ struct QQmlVMEMetaData } }; +class QQmlVMEMetaObject; +class QQmlVMEVariantQObjectPtr : public QQmlGuard +{ +public: + inline QQmlVMEVariantQObjectPtr(); + inline ~QQmlVMEVariantQObjectPtr(); + inline void objectDestroyed(QObject *); + inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index); + + QQmlVMEMetaObject *m_target; + int m_index; +}; + class QV8QObjectWrapper; class QQmlVMEVariant; class QQmlRefCount; @@ -163,6 +176,7 @@ protected: private: friend class QQmlVMEMetaObjectEndpoint; + friend class QQmlVMEVariantQObjectPtr; QObject *object; QQmlCompiledData *compiledData; diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index 78b2cb719c..5842e29257 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -1043,7 +1043,7 @@ v8::Handle QV8QObjectWrapper::newQObject(QObject *object) return v8::Null(); if (QObjectPrivate::get(object)->wasDeleted) - return v8::Undefined(); + return v8::Null(); QQmlData *ddata = QQmlData::get(object, true); diff --git a/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.3.qml b/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.3.qml new file mode 100644 index 0000000000..3739150bc4 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/dynamicDeletion.3.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + id: root + property bool test: false + property QtObject objectProperty + + onObjectPropertyChanged: { + root.test = true; + } + + property Component c: Component { + id: dynamicComponent + QtObject { + id: dynamicObject + } + } + + function create() { + root.objectProperty = root.c.createObject(root); + } + + function destroy() { + root.test = false; // reset test + root.objectProperty.destroy(100); + // in cpp, wait objectProperty deletion, inspect "test" and "objectProperty" + // test should be true and value of objectProperty should be zero. + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 8fea635b68..e3ad1e71cb 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -1288,6 +1288,28 @@ void tst_qqmlecmascript::dynamicDestruction() delete o; } + + { + // QTBUG-23451 + QQmlGuard createdQmlObject = 0; + QQmlComponent component(&engine, testFileUrl("dynamicDeletion.3.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + QVERIFY(qvariant_cast(o->property("objectProperty")) == 0); + QMetaObject::invokeMethod(o, "create"); + createdQmlObject = qvariant_cast(o->property("objectProperty")); + QVERIFY(createdQmlObject); + QMetaObject::invokeMethod(o, "destroy"); + QVERIFY(qvariant_cast(o->property("test")) == false); + for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up + QTest::qWait(100); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + } + QVERIFY(qvariant_cast(o->property("objectProperty")) == 0); + QVERIFY(qvariant_cast(o->property("test")) == true); + delete o; + } } /* -- cgit v1.2.3 From 5ae8caba10a79c2298939aff777a0201959a94af Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 9 Mar 2012 09:16:50 +0100 Subject: Remove binding dependency on QQmlExpression This is the first step to creating much lighter weight bindings that are tuned for the specific scenario in which they're used. Change-Id: Ib985dcff25679b711b5c634bbc891aa7902bf405 Reviewed-by: Michael Brasser --- src/qml/debugger/qqmlenginedebugservice.cpp | 4 +- src/qml/qml/qml.pri | 1 - src/qml/qml/qqmlabstractbinding.cpp | 7 + src/qml/qml/qqmlabstractbinding_p.h | 1 + src/qml/qml/qqmlbinding.cpp | 267 ++++++++++++--------- src/qml/qml/qqmlbinding_p.h | 77 +++++- src/qml/qml/qqmlbinding_p_p.h | 89 ------- src/qml/qml/qqmlcomponent.cpp | 7 +- src/qml/qml/qqmlengine.cpp | 2 - src/qml/qml/qqmlexpression.cpp | 159 +----------- src/qml/qml/qqmlexpression.h | 2 - src/qml/qml/qqmlexpression_p.h | 13 +- src/qml/qml/qqmljavascriptexpression.cpp | 109 +++++++++ src/qml/qml/qqmljavascriptexpression_p.h | 9 + src/qml/qml/qqmlproperty.cpp | 18 -- src/qml/qml/qqmlproperty_p.h | 5 - src/qml/qml/qqmlvme.cpp | 9 +- src/qml/qml/v8/qv8bindings.cpp | 6 +- src/qml/qml/v8/qv8qobjectwrapper.cpp | 5 +- src/qml/qml/v8/qv8valuetypewrapper.cpp | 4 +- src/quick/items/qquickstateoperations.cpp | 12 +- src/quick/qtquick2.cpp | 5 +- src/quick/util/qquickpropertychanges.cpp | 11 +- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 6 +- tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 42 ++-- 25 files changed, 400 insertions(+), 470 deletions(-) delete mode 100644 src/qml/qml/qqmlbinding_p_p.h diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 9653cf674f..892098bd93 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -577,10 +577,8 @@ void QQmlEngineDebugService::setBinding(int objectId, QQmlPropertyPrivate::setSignalExpression(property, qmlExpression); qmlExpression->setSourceLocation(filename, line, column); } else if (property.isProperty()) { - QQmlBinding *binding = new QQmlBinding(expression.toString(), object, context); + QQmlBinding *binding = new QQmlBinding(expression.toString(), false, object, QQmlContextData::get(context), filename, line, column);; binding->setTarget(property); - binding->setSourceLocation(filename, line, column); - binding->setNotifyOnValueChanged(true); QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::setBinding(property, binding); if (oldBinding) oldBinding->destroy(); diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 763a260b54..c75e4c9681 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -64,7 +64,6 @@ HEADERS += \ $$PWD/qqml.h \ $$PWD/qquickapplication_p.h \ $$PWD/qqmlbinding_p.h \ - $$PWD/qqmlbinding_p_p.h \ $$PWD/qqmlproperty.h \ $$PWD/qqmlcomponent.h \ $$PWD/qqmlcomponent_p.h \ diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index 11e4ed2ed8..acc207e970 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -41,6 +41,7 @@ #include "qqmlabstractbinding_p.h" +#include #include #include @@ -154,6 +155,12 @@ void QQmlAbstractBinding::removeFromObject() } } +void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) +{ + qmlInfo(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); +} + + static void bindingDummyDeleter(QQmlAbstractBinding *) { } diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h index d226e177bd..8c4aa4affc 100644 --- a/src/qml/qml/qqmlabstractbinding_p.h +++ b/src/qml/qml/qqmlabstractbinding_p.h @@ -92,6 +92,7 @@ public: void removeFromObject(); static inline Pointer getPointer(QQmlAbstractBinding *p); + static void printBindingLoopError(QQmlProperty &prop); protected: virtual ~QQmlAbstractBinding(); diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 23f5abf5fd..f43822ed0e 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qqmlbinding_p.h" -#include "qqmlbinding_p_p.h" #include "qqml.h" #include "qqmlcontext.h" @@ -49,6 +48,8 @@ #include "qqmldata_p.h" #include #include +#include +#include #include #include @@ -57,24 +58,9 @@ QT_BEGIN_NAMESPACE QQmlBinding::Identifier QQmlBinding::Invalid = -1; -void QQmlBindingPrivate::refresh() -{ - Q_Q(QQmlBinding); - q->update(); -} - -QQmlBindingPrivate::QQmlBindingPrivate() -: updating(false), enabled(false), target(), targetProperty(0) -{ -} - -QQmlBindingPrivate::~QQmlBindingPrivate() -{ -} - QQmlBinding * QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt, - const QString &url, int lineNumber, QObject *parent) + const QString &url, int lineNumber) { if (id < 0) return 0; @@ -88,7 +74,8 @@ QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt, typeData = engine->typeLoader.get(ctxtdata->url); cdata = typeData->compiledData(); } - QQmlBinding *rv = cdata ? new QQmlBinding(cdata->primitives.at(id), true, obj, ctxtdata, url, lineNumber, 0, parent) : 0; + QQmlBinding *rv = cdata ? new QQmlBinding(cdata->primitives.at(id), true, obj, ctxtdata, + url, lineNumber, 0) : 0; if (cdata) cdata->release(); if (typeData) @@ -96,30 +83,62 @@ QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt, return rv; } -QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt, - QObject *parent) -: QQmlExpression(QQmlContextData::get(ctxt), obj, str, *new QQmlBindingPrivate) +static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = { + QQmlBinding::expressionIdentifier, + QQmlBinding::expressionChanged +}; + +QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt) +: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), m_lineNumber(-1), m_columnNumber(-1) { - setParent(parent); setNotifyOnValueChanged(true); + QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt)); + setScopeObject(obj); + + QQmlRewrite::RewriteBinding rewriteBinding; + QString code = rewriteBinding(str); + + m_expression = str.toUtf8(); + v8function = evalFunction(context(), obj, code, QString(), 0); } -QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt, - QObject *parent) -: QQmlExpression(ctxt, obj, str, *new QQmlBindingPrivate) +QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt) +: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), m_lineNumber(-1), m_columnNumber(-1) { - setParent(parent); setNotifyOnValueChanged(true); + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(obj); + + QQmlRewrite::RewriteBinding rewriteBinding; + QString code = rewriteBinding(str); + + m_expression = str.toUtf8(); + v8function = evalFunction(ctxt, obj, code, QString(), 0); } QQmlBinding::QQmlBinding(const QString &str, bool isRewritten, QObject *obj, - QQmlContextData *ctxt, - const QString &url, int lineNumber, int columnNumber, - QObject *parent) -: QQmlExpression(ctxt, obj, str, isRewritten, url, lineNumber, columnNumber, *new QQmlBindingPrivate) + QQmlContextData *ctxt, + const QString &url, int lineNumber, int columnNumber) +: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), m_lineNumber(-1), m_columnNumber(-1) { - setParent(parent); setNotifyOnValueChanged(true); + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(obj); + + QString code; + if (isRewritten) { + code = str; + } else { + QQmlRewrite::RewriteBinding rewriteBinding; + code = rewriteBinding(str); + } + + m_url = url; + m_lineNumber = lineNumber; + m_columnNumber = columnNumber; + m_expression = str.toUtf8(); + + v8function = evalFunction(ctxt, obj, code, url, lineNumber); } /*! @@ -130,124 +149,100 @@ QQmlBinding::QQmlBinding(const QString &str, bool isRewritten, QObject *obj, v8::Handle function; new QQmlBinding(&function, scope, ctxt); */ -QQmlBinding::QQmlBinding(void *functionPtr, QObject *obj, QQmlContextData *ctxt, - QObject *parent) -: QQmlExpression(ctxt, obj, functionPtr, *new QQmlBindingPrivate) +QQmlBinding::QQmlBinding(void *functionPtr, QObject *obj, QQmlContextData *ctxt, + const QString &url, int lineNumber, int columnNumber) +: QQmlJavaScriptExpression(&QQmlBinding_jsvtable), + m_url(url), m_lineNumber(lineNumber), m_columnNumber(columnNumber) { - setParent(parent); setNotifyOnValueChanged(true); -} - -QQmlBinding::~QQmlBinding() -{ -} + QQmlAbstractExpression::setContext(ctxt); + setScopeObject(obj); -void QQmlBinding::setTarget(const QQmlProperty &prop) -{ - Q_D(QQmlBinding); - d->property = prop; - d->target = d->property.object(); - d->targetProperty = QQmlPropertyPrivate::get(d->property)->core.encodedIndex(); - - update(); + v8function = qPersistentNew(*(v8::Handle *)functionPtr); } -void QQmlBinding::setTarget(QObject *object, - const QQmlPropertyData &core, - QQmlContextData *ctxt) +QQmlBinding::~QQmlBinding() { - Q_D(QQmlBinding); - d->property = QQmlPropertyPrivate::restore(object, core, ctxt); - d->target = d->property.object(); - d->targetProperty = QQmlPropertyPrivate::get(d->property)->core.encodedIndex(); - - update(); + qPersistentDispose(v8function); } -QQmlProperty QQmlBinding::property() const +void QQmlBinding::setEvaluateFlags(EvaluateFlags flags) { - Q_D(const QQmlBinding); - return d->property; + setRequiresThisObject(flags & RequiresThisObject); } -void QQmlBinding::setEvaluateFlags(EvaluateFlags flags) +QQmlBinding::EvaluateFlags QQmlBinding::evaluateFlags() const { - Q_D(QQmlBinding); - d->setRequiresThisObject(flags & RequiresThisObject); + return requiresThisObject()?RequiresThisObject:None; } -QQmlBinding::EvaluateFlags QQmlBinding::evaluateFlags() const +void QQmlBinding::setNotifyOnValueChanged(bool v) { - Q_D(const QQmlBinding); - return d->requiresThisObject()?RequiresThisObject:None; + QQmlJavaScriptExpression::setNotifyOnValueChanged(v); } void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) { - Q_D(QQmlBinding); - - if (!d->enabled || !d->context() || !d->context()->isValid()) + if (!enabledFlag() || !context() || !context()->isValid()) return; QQmlTrace trace("General Binding Update"); - trace.addDetail("URL", d->url); - trace.addDetail("Line", d->line); - trace.addDetail("Column", d->columnNumber); + trace.addDetail("URL", m_url); + trace.addDetail("Line", m_lineNumber); + trace.addDetail("Column", m_columnNumber); - if (!d->updating) { - QQmlBindingProfiler prof(d->url, d->line, d->column); + if (!updatingFlag()) { + QQmlBindingProfiler prof(m_url, m_lineNumber, m_columnNumber); if (prof.enabled) prof.addDetail(expression()); - d->updating = true; + setUpdatingFlag(true); - QQmlAbstractExpression::DeleteWatcher watcher(d); + QQmlAbstractExpression::DeleteWatcher watcher(this); - if (d->property.propertyType() == qMetaTypeId()) { + if (m_core.propType == qMetaTypeId()) { - int idx = d->property.index(); + int idx = m_core.coreIndex; Q_ASSERT(idx != -1); QQmlBinding *t = this; int status = -1; void *a[] = { &t, 0, &status, &flags }; - QMetaObject::metacall(d->property.object(), - QMetaObject::WriteProperty, - idx, a); + QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a); } else { - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(d->context()->engine); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); ep->referenceScarceResources(); bool isUndefined = false; v8::HandleScope handle_scope; v8::Context::Scope scope(ep->v8engine()->context()); - v8::Local result = d->v8value(0, &isUndefined); + v8::Local result = + QQmlJavaScriptExpression::evaluate(context(), v8function, &isUndefined); trace.event("writing binding result"); bool needsErrorData = false; - if (!watcher.wasDeleted() && !d->hasError()) - needsErrorData = !QQmlPropertyPrivate::writeBinding(d->property, d->context(), - d, result, - isUndefined, flags); + if (!watcher.wasDeleted() && !hasError()) + needsErrorData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(), + this, result, isUndefined, flags); if (!watcher.wasDeleted()) { if (needsErrorData) { - QUrl url = QUrl(d->url); - int line = d->line; + QUrl url = QUrl(m_url); + if (url.isEmpty()) url = QUrl(QLatin1String("")); - d->delayedError()->error.setUrl(url); - d->delayedError()->error.setLine(line); - d->delayedError()->error.setColumn(-1); + delayedError()->error.setUrl(url); + delayedError()->error.setLine(m_lineNumber); + delayedError()->error.setColumn(m_columnNumber); } - if (d->hasError()) { - if (!d->delayedError()->addError(ep)) ep->warning(this->error()); + if (hasError()) { + if (!delayedError()->addError(ep)) ep->warning(this->error()); } else { - d->clearError(); + clearError(); } } @@ -256,62 +251,96 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) } if (!watcher.wasDeleted()) - d->updating = false; + setUpdatingFlag(false); } else { - QQmlBindingPrivate::printBindingLoopError(d->property); + QQmlProperty p = property(); + QQmlAbstractBinding::printBindingLoopError(p); } } -void QQmlBindingPrivate::printBindingLoopError(QQmlProperty &prop) +QVariant QQmlBinding::evaluate() +{ + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); + ep->referenceScarceResources(); + + bool isUndefined = false; + + v8::HandleScope handle_scope; + v8::Context::Scope scope(ep->v8engine()->context()); + v8::Local result = + QQmlJavaScriptExpression::evaluate(context(), v8function, &isUndefined); + + ep->dereferenceScarceResources(); + + return ep->v8engine()->toVariant(result, qMetaTypeId >()); +} + +QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e) { - qmlInfo(prop.object()) << QQmlBinding::tr("Binding loop detected for property \"%1\"").arg(prop.name()); + QQmlBinding *This = static_cast(e); + + return QLatin1String("\"") + QString::fromUtf8(This->m_expression) + QLatin1String("\""); } -void QQmlBindingPrivate::expressionChanged() +void QQmlBinding::expressionChanged(QQmlJavaScriptExpression *e) { - Q_Q(QQmlBinding); - q->update(); + QQmlBinding *This = static_cast(e); + This->update(); +} + +void QQmlBinding::refresh() +{ + update(); } void QQmlBinding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags) { - Q_D(QQmlBinding); - d->enabled = e; + setEnabledFlag(e); setNotifyOnValueChanged(e); if (e) update(flags); } -bool QQmlBinding::enabled() const +QString QQmlBinding::expression() const { - Q_D(const QQmlBinding); - - return d->enabled; + return QString::fromUtf8(m_expression); } -QString QQmlBinding::expression() const +QObject *QQmlBinding::object() const { - return QQmlExpression::expression(); + if (m_coreObject.hasValue()) return m_coreObject.constValue()->target; + else return *m_coreObject; } int QQmlBinding::propertyIndex() const { - Q_D(const QQmlBinding); - return d->targetProperty; + if (m_coreObject.hasValue()) return m_coreObject.constValue()->targetProperty; + else return m_core.encodedIndex(); } -QObject *QQmlBinding::object() const +void QQmlBinding::retargetBinding(QObject *t, int i) { - Q_D(const QQmlBinding); - return d->target; + m_coreObject.value().target = t; + m_coreObject.value().targetProperty = i; } -void QQmlBinding::retargetBinding(QObject *t, int i) +void QQmlBinding::setTarget(const QQmlProperty &prop) +{ + setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core, + QQmlPropertyPrivate::get(prop)->context); +} + +void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, QQmlContextData *ctxt) +{ + m_coreObject = object; + m_core = core; + m_ctxt = ctxt; +} + +QQmlProperty QQmlBinding::property() const { - Q_D(QQmlBinding); - d->target = t; - d->targetProperty = i; + return QQmlPropertyPrivate::restore(object(), m_core, *m_ctxt); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 785c96fd22..2cf7b80290 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -64,23 +64,26 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE class QQmlContext; -class QQmlBindingPrivate; -class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlExpression, public QQmlAbstractBinding +class Q_QML_PRIVATE_EXPORT QQmlBinding : public QQmlJavaScriptExpression, + public QQmlAbstractExpression, + public QQmlAbstractBinding { -Q_OBJECT public: enum EvaluateFlag { None = 0x00, RequiresThisObject = 0x01 }; Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag) - QQmlBinding(const QString &, QObject *, QQmlContext *, QObject *parent=0); - QQmlBinding(const QString &, QObject *, QQmlContextData *, QObject *parent=0); + QQmlBinding(const QString &, QObject *, QQmlContext *); + QQmlBinding(const QString &, QObject *, QQmlContextData *); QQmlBinding(const QString &, bool isRewritten, QObject *, QQmlContextData *, - const QString &url, int lineNumber, int columnNumber = 0, QObject *parent=0); - QQmlBinding(void *, QObject *, QQmlContextData *, QObject *parent=0); + const QString &url, int lineNumber, int columnNumber); + QQmlBinding(void *, QObject *, QQmlContextData *, + const QString &url, int lineNumber, int columnNumber); void setTarget(const QQmlProperty &); void setTarget(QObject *, const QQmlPropertyData &, QQmlContextData *); @@ -89,32 +92,80 @@ public: void setEvaluateFlags(EvaluateFlags flags); EvaluateFlags evaluateFlags() const; - bool enabled() const; + void setNotifyOnValueChanged(bool); + + // Inherited from QQmlAbstractExpression + virtual void refresh(); // Inherited from QQmlAbstractBinding virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags); virtual void update(QQmlPropertyPrivate::WriteFlags flags); virtual QString expression() const; - virtual int propertyIndex() const; virtual QObject *object() const; + virtual int propertyIndex() const; virtual void retargetBinding(QObject *, int); typedef int Identifier; static Identifier Invalid; - static QQmlBinding *createBinding(Identifier, QObject *, QQmlContext *, - const QString &, int, QObject *parent=0); + static QQmlBinding *createBinding(Identifier, QObject *, QQmlContext *, const QString &, int); -public Q_SLOTS: + QVariant evaluate(); void update() { update(QQmlPropertyPrivate::DontRemoveBinding); } + static QString expressionIdentifier(QQmlJavaScriptExpression *); + static void expressionChanged(QQmlJavaScriptExpression *); + protected: ~QQmlBinding(); private: - Q_DECLARE_PRIVATE(QQmlBinding) + v8::Persistent v8function; + + inline bool updatingFlag() const; + inline void setUpdatingFlag(bool); + inline bool enabledFlag() const; + inline void setEnabledFlag(bool); + + struct Retarget { + QObject *target; + int targetProperty; + }; + + QPointerValuePair m_coreObject; + QQmlPropertyData m_core; + // We store some flag bits in the following flag pointers. + // m_ctxt:flag1 - updatingFlag + // m_ctxt:flag2 - enabledFlag + QFlagPointer m_ctxt; + + // XXX It would be good if we could get rid of these in most circumstances + QString m_url; + int m_lineNumber; + int m_columnNumber; + QByteArray m_expression; }; +bool QQmlBinding::updatingFlag() const +{ + return m_ctxt.flag(); +} + +void QQmlBinding::setUpdatingFlag(bool v) +{ + m_ctxt.setFlagValue(v); +} + +bool QQmlBinding::enabledFlag() const +{ + return m_ctxt.flag2(); +} + +void QQmlBinding::setEnabledFlag(bool v) +{ + m_ctxt.setFlag2Value(v); +} + Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlBinding::EvaluateFlags) QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding_p_p.h b/src/qml/qml/qqmlbinding_p_p.h deleted file mode 100644 index b53c903916..0000000000 --- a/src/qml/qml/qqmlbinding_p_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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. -** -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLBINDING_P_P_H -#define QQMLBINDING_P_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 "qqmlbinding_p.h" - -#include "qqmlproperty.h" -#include "qqmlexpression_p.h" - -QT_BEGIN_NAMESPACE - -class QQmlBindingPrivate : public QQmlExpressionPrivate -{ - Q_DECLARE_PUBLIC(QQmlBinding) -public: - QQmlBindingPrivate(); - ~QQmlBindingPrivate(); - - virtual void expressionChanged(); - - static void printBindingLoopError(QQmlProperty &prop); - -protected: - virtual void refresh(); - -private: - bool updating:1; - bool enabled:1; - int columnNumber; - QQmlProperty property; - - QObject *target; - int targetProperty; -}; - -QT_END_NAMESPACE - -#endif // QQMLBINDING_P_P_H diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 79100c4394..a73fe7cd63 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -50,13 +50,13 @@ #include "qqml.h" #include "qqmlengine.h" #include "qqmlbinding_p.h" -#include "qqmlbinding_p_p.h" #include "qqmlglobal_p.h" #include "qqmlscript_p.h" #include #include #include "qqmlincubator.h" #include "qqmlincubator_p.h" +#include #include #include @@ -1337,9 +1337,8 @@ void QV8IncubatorResource::statusChanged(Status s) f->Call(me, 1, args); if (tc.HasCaught()) { QQmlError error; - QQmlExpressionPrivate::exceptionToError(tc.Message(), error); - QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), - error); + QQmlJavaScriptExpression::exceptionToError(tc.Message(), error); + QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()), error); } } } diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 0c8ff6ae27..489b4f895a 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -49,7 +49,6 @@ #include "qqmlcontext.h" #include "qqmlexpression.h" #include "qqmlcomponent.h" -#include "qqmlbinding_p_p.h" #include "qqmlvme_p.h" #include #include "qqmlstringconverters_p.h" @@ -176,7 +175,6 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int void QQmlEnginePrivate::defineModule() { registerBaseTypes("QtQuick", 2, 0); - qmlRegisterType(); qmlRegisterUncreatableType("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class")); qmlRegisterUncreatableType("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()")); } diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index cefde1decb..60a0fe1c89 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -72,8 +72,7 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate() dataRef = 0; } -void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, - QObject *me) +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me) { expression = expr; @@ -83,22 +82,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, expressionFunctionRewritten = false; } -void QQmlExpressionPrivate::init(QQmlContextData *ctxt, v8::Handle func, - QObject *me) -{ - QQmlAbstractExpression::setContext(ctxt); - setScopeObject(me); - - v8function = qPersistentNew(func); - setUseSharedContext(false); - expressionFunctionValid = true; - expressionFunctionRewritten = false; - extractExpressionFromFunction = true; -} - void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, - bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) { url = srcUrl; line = lineNumber; @@ -114,8 +100,8 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, } void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, - bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) { url = srcUrl; line = lineNumber; @@ -140,97 +126,13 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, setScopeObject(me); } -// Callee owns the persistent handle -v8::Persistent -QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, - const char *code, int codeLength, - const QString &filename, int line, - v8::Persistent *qmlscope) -{ - QQmlEngine *engine = ctxt->engine; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - - v8::HandleScope handle_scope; - v8::Context::Scope ctxtscope(ep->v8engine()->context()); - - v8::TryCatch tc; - v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); - v8::Local script = ep->v8engine()->qmlModeCompile(code, codeLength, filename, line); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function compilation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent(); - } - v8::Local result = script->Run(scopeobject); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function evaluation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent(); - } - if (qmlscope) *qmlscope = qPersistentNew(scopeobject); - return qPersistentNew(v8::Local::Cast(result)); -} - -// Callee owns the persistent handle -v8::Persistent -QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, - const QString &code, const QString &filename, int line, - v8::Persistent *qmlscope) -{ - QQmlEngine *engine = ctxt->engine; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - - v8::HandleScope handle_scope; - v8::Context::Scope ctxtscope(ep->v8engine()->context()); - - v8::TryCatch tc; - v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); - v8::Local script = ep->v8engine()->qmlModeCompile(code, filename, line); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function compilation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent(); - } - v8::Local result = script->Run(scopeobject); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function evaluation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent(); - } - if (qmlscope) *qmlscope = qPersistentNew(scopeobject); - return qPersistentNew(v8::Local::Cast(result)); -} - QQmlExpression * QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, - const QString &expr, bool isRewritten, - const QString &url, int lineNumber, int columnNumber) + const QString &expr, bool isRewritten, + const QString &url, int lineNumber, int columnNumber) { - return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, *new QQmlExpressionPrivate); + return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, + *new QQmlExpressionPrivate); } /*! @@ -382,24 +284,6 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, d->init(ctxt, expression, scope); } -/*! - \internal - - To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle. - For example: - v8::Handle function; - new QQmlExpression(ctxt, scope, &function, ...); - */ -QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, void *functionPtr, - QQmlExpressionPrivate &dd) -: QObject(dd, 0) -{ - v8::Handle function = *(v8::Handle *)functionPtr; - - Q_D(QQmlExpression); - d->init(ctxt, function, scope); -} - /*! Destroy the QQmlExpression instance. */ @@ -463,31 +347,6 @@ void QQmlExpression::setExpression(const QString &expression) qPersistentDispose(d->v8qmlscope); } -void QQmlExpressionPrivate::exceptionToError(v8::Handle message, - QQmlError &error) -{ - Q_ASSERT(!message.IsEmpty()); - - v8::Handle name = message->GetScriptResourceName(); - v8::Handle description = message->Get(); - int lineNumber = message->GetLineNumber(); - - v8::Local file = name->IsString()?name->ToString():v8::Local(); - if (file.IsEmpty() || file->Length() == 0) - error.setUrl(QUrl(QLatin1String(""))); - else - error.setUrl(QUrl(QV8Engine::toStringStatic(file))); - - error.setLine(lineNumber); - error.setColumn(-1); - - QString qDescription = QV8Engine::toStringStatic(description); - if (qDescription.startsWith(QLatin1String("Uncaught "))) - qDescription = qDescription.mid(9 /* strlen("Uncaught ") */); - - error.setDescription(qDescription); -} - // Must be called with a valid handle scope v8::Local QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined) { diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h index 4044546fbf..b60d9f1f86 100644 --- a/src/qml/qml/qqmlexpression.h +++ b/src/qml/qml/qqmlexpression.h @@ -96,8 +96,6 @@ Q_SIGNALS: protected: QQmlExpression(QQmlContextData *, QObject *, const QString &, QQmlExpressionPrivate &dd); - QQmlExpression(QQmlContextData *, QObject *, void *, - QQmlExpressionPrivate &dd); QQmlExpression(QQmlContextData *, QObject *, const QString &, bool, const QString &, int, int, QQmlExpressionPrivate &dd); QQmlExpression(QQmlContextData *, QObject *, const QByteArray &, bool, diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h index 3b335ba658..186e3aebf9 100644 --- a/src/qml/qml/qqmlexpression_p.h +++ b/src/qml/qml/qqmlexpression_p.h @@ -79,7 +79,6 @@ public: ~QQmlExpressionPrivate(); void init(QQmlContextData *, const QString &, QObject *); - void init(QQmlContextData *, v8::Handle, QObject *); void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, int, int); void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, int, int); @@ -92,18 +91,8 @@ public: void _q_notify(); - static void exceptionToError(v8::Handle, QQmlError &); - static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, - const QString &code, const QString &filename, - int line, - v8::Persistent *qmlscope = 0); - static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, - const char *code, int codeLength, - const QString &filename, int line, - v8::Persistent *qmlscope = 0); - static QQmlExpression *create(QQmlContextData *, QObject *, const QString &, bool, - const QString &, int, int); + const QString &, int, int); bool expressionFunctionValid:1; bool expressionFunctionRewritten:1; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 4186b5b53d..560e0f1342 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -251,6 +251,115 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError() return &m_vtable.value(); } +void QQmlJavaScriptExpression::exceptionToError(v8::Handle message, QQmlError &error) +{ + Q_ASSERT(!message.IsEmpty()); + + v8::Handle name = message->GetScriptResourceName(); + v8::Handle description = message->Get(); + int lineNumber = message->GetLineNumber(); + + v8::Local file = name->IsString()?name->ToString():v8::Local(); + if (file.IsEmpty() || file->Length() == 0) + error.setUrl(QUrl(QLatin1String(""))); + else + error.setUrl(QUrl(QV8Engine::toStringStatic(file))); + + error.setLine(lineNumber); + error.setColumn(-1); + + QString qDescription = QV8Engine::toStringStatic(description); + if (qDescription.startsWith(QLatin1String("Uncaught "))) + qDescription = qDescription.mid(9 /* strlen("Uncaught ") */); + + error.setDescription(qDescription); +} + +// Callee owns the persistent handle +v8::Persistent +QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scope, + const char *code, int codeLength, + const QString &filename, int line, + v8::Persistent *qmlscope) +{ + QQmlEngine *engine = ctxt->engine; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + + v8::HandleScope handle_scope; + v8::Context::Scope ctxtscope(ep->v8engine()->context()); + + v8::TryCatch tc; + v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); + v8::Local script = ep->v8engine()->qmlModeCompile(code, codeLength, filename, line); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function compilation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + v8::Local result = script->Run(scopeobject); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function evaluation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + if (qmlscope) *qmlscope = qPersistentNew(scopeobject); + return qPersistentNew(v8::Local::Cast(result)); +} + +// Callee owns the persistent handle +v8::Persistent +QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scope, + const QString &code, const QString &filename, int line, + v8::Persistent *qmlscope) +{ + QQmlEngine *engine = ctxt->engine; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + + v8::HandleScope handle_scope; + v8::Context::Scope ctxtscope(ep->v8engine()->context()); + + v8::TryCatch tc; + v8::Local scopeobject = ep->v8engine()->qmlScope(ctxt, scope); + v8::Local script = ep->v8engine()->qmlModeCompile(code, filename, line); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function compilation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + v8::Local result = script->Run(scopeobject); + if (tc.HasCaught()) { + QQmlError error; + error.setDescription(QLatin1String("Exception occurred during function evaluation")); + error.setLine(line); + error.setUrl(QUrl::fromLocalFile(filename)); + v8::Local message = tc.Message(); + if (!message.IsEmpty()) + QQmlExpressionPrivate::exceptionToError(message, error); + ep->warning(error); + return v8::Persistent(); + } + if (qmlscope) *qmlscope = qPersistentNew(scopeobject); + return qPersistentNew(v8::Local::Cast(result)); +} + void QQmlJavaScriptExpression::clearGuards() { while (Guard *g = activeGuards.takeFirst()) diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 1da1e12ebd..5d790e4570 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -132,6 +132,15 @@ public: void clearError(); QQmlDelayedError *delayedError(); + static void exceptionToError(v8::Handle, QQmlError &); + static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, + const QString &code, const QString &filename, + int line, + v8::Persistent *qmlscope = 0); + static v8::Persistent evalFunction(QQmlContextData *ctxt, QObject *scope, + const char *code, int codeLength, + const QString &filename, int line, + v8::Persistent *qmlscope = 0); protected: ~QQmlJavaScriptExpression(); diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 8d5d83ee1b..14778ce6c8 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1521,24 +1521,6 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, return true; } -bool QQmlPropertyPrivate::writeBinding(const QQmlProperty &that, - QQmlContextData *context, - QQmlJavaScriptExpression *expression, - v8::Handle result, bool isUndefined, - WriteFlags flags) -{ - QQmlPropertyPrivate *pp = that.d; - - if (!pp) - return true; - - QObject *object = that.object(); - if (!object) - return true; - - return writeBinding(object, pp->core, context, expression, result, isUndefined, flags); -} - const QMetaObject *QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType) { if (engine) { diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index dc0235517d..f4a9ced53b 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -144,11 +144,6 @@ public: static QQmlExpression *setSignalExpression(const QQmlProperty &that, QQmlExpression *) ; static bool write(const QQmlProperty &that, const QVariant &, WriteFlags); - static bool writeBinding(const QQmlProperty &that, - QQmlContextData *context, - QQmlJavaScriptExpression *expression, - v8::Handle result, bool isUndefined, - WriteFlags flags); static bool writeBinding(QObject *, const QQmlPropertyData &, QQmlContextData *context, QQmlJavaScriptExpression *expression, diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 99979ab617..2a7ea45053 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -57,7 +57,6 @@ #include "qqmlengine_p.h" #include "qqmlcomponent_p.h" #include "qqmlvmemetaobject_p.h" -#include "qqmlbinding_p_p.h" #include "qqmlcontext_p.h" #include #include @@ -765,8 +764,8 @@ QObject *QQmlVME::run(QList *errors, QML_NEXT_INSTR(StoreBinding); QQmlBinding *bind = new QQmlBinding(PRIMITIVES.at(instr.value), true, - context, CTXT, COMP->name, instr.line, - instr.column); + context, CTXT, COMP->name, instr.line, + instr.column); bindValues.push(bind); bind->m_mePtr = &bindValues.top(); bind->setTarget(target, instr.property, CTXT); @@ -788,8 +787,8 @@ QObject *QQmlVME::run(QList *errors, QML_NEXT_INSTR(StoreBindingOnAlias); QQmlBinding *bind = new QQmlBinding(PRIMITIVES.at(instr.value), true, - context, CTXT, COMP->name, instr.line, - instr.column); + context, CTXT, COMP->name, instr.line, + instr.column); bindValues.push(bind); bind->m_mePtr = &bindValues.top(); bind->setTarget(target, instr.property, CTXT); diff --git a/src/qml/qml/v8/qv8bindings.cpp b/src/qml/qml/v8/qv8bindings.cpp index 76fbea137e..4b96679cf3 100644 --- a/src/qml/qml/v8/qv8bindings.cpp +++ b/src/qml/qml/v8/qv8bindings.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -157,9 +156,8 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags) ep->dereferenceScarceResources(); } else { - QQmlProperty p = QQmlPropertyPrivate::restore(target, instruction->property, - context); - QQmlBindingPrivate::printBindingLoopError(p); + QQmlProperty p = QQmlPropertyPrivate::restore(target, instruction->property, context); + QQmlAbstractBinding::printBindingLoopError(p); } } diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index 5842e29257..a483346dd1 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -589,11 +589,10 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert v8::StackTrace::kScriptName)); v8::Local frame = trace->GetFrame(0); int lineNumber = frame->GetLineNumber(); - int columNumber = frame->GetColumn(); + int columnNumber = frame->GetColumn(); QString url = engine->toString(frame->GetScriptName()); - newBinding = new QQmlBinding(&function, object, context); - newBinding->setSourceLocation(url, lineNumber, columNumber); + newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber); newBinding->setTarget(object, *property, context); newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QQmlBinding::RequiresThisObject); diff --git a/src/qml/qml/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp index 54d871d5f0..7a3c675d49 100644 --- a/src/qml/qml/v8/qv8valuetypewrapper.cpp +++ b/src/qml/qml/v8/qv8valuetypewrapper.cpp @@ -345,8 +345,8 @@ v8::Handle QV8ValueTypeWrapper::Setter(v8::Local property int columnNumber = frame->GetColumn(); QString url = r->engine->toString(frame->GetScriptName()); - newBinding = new QQmlBinding(&function, reference->object, context); - newBinding->setSourceLocation(url, lineNumber, columnNumber); + newBinding = new QQmlBinding(&function, reference->object, context, + url, lineNumber, columnNumber); newBinding->setTarget(reference->object, cacheData, context); newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QQmlBinding::RequiresThisObject); diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index 668c7c07d7..a6a4e31aba 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -318,7 +318,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction xa; xa.property = property; - xa.toBinding = newBinding; + xa.toBinding = QQmlAbstractBinding::getPointer(newBinding); xa.fromValue = xa.property.read(); xa.deletableToBinding = true; actions << xa; @@ -338,7 +338,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction ya; ya.property = property; - ya.toBinding = newBinding; + ya.toBinding = QQmlAbstractBinding::getPointer(newBinding); ya.fromValue = ya.property.read(); ya.deletableToBinding = true; actions << ya; @@ -358,7 +358,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction sa; sa.property = property; - sa.toBinding = newBinding; + sa.toBinding = QQmlAbstractBinding::getPointer(newBinding); sa.fromValue = sa.property.read(); sa.deletableToBinding = true; actions << sa; @@ -378,7 +378,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction ra; ra.property = property; - ra.toBinding = newBinding; + ra.toBinding = QQmlAbstractBinding::getPointer(newBinding); ra.fromValue = ra.property.read(); ra.deletableToBinding = true; actions << ra; @@ -398,7 +398,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction wa; wa.property = property; - wa.toBinding = newBinding; + wa.toBinding = QQmlAbstractBinding::getPointer(newBinding); wa.fromValue = wa.property.read(); wa.deletableToBinding = true; actions << wa; @@ -418,7 +418,7 @@ QQuickStateOperation::ActionList QQuickParentChange::actions() newBinding->setTarget(property); QQuickAction ha; ha.property = property; - ha.toBinding = newBinding; + ha.toBinding = QQmlAbstractBinding::getPointer(newBinding); ha.fromValue = ha.property.read(); ha.deletableToBinding = true; actions << ha; diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp index 621c3ff18e..32a9d382f2 100644 --- a/src/quick/qtquick2.cpp +++ b/src/quick/qtquick2.cpp @@ -135,10 +135,11 @@ void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context, QQmlBinding *newBinding = 0; if (!isLiteralValue) { - newBinding = new QQmlBinding(expression.toString(), object, context); + newBinding = new QQmlBinding(expression.toString(), false, object, + QQmlContextData::get(context), fileName, + line, column); newBinding->setTarget(property); newBinding->setNotifyOnValueChanged(true); - newBinding->setSourceLocation(fileName, line, column); } state->changeBindingInRevertList(object, propertyName, newBinding); diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 83ddb2530e..8b0818c96c 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -478,12 +478,11 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() QQmlBinding::Identifier id = d->expressions.at(ii).id; QQmlBinding *newBinding = id != QQmlBinding::Invalid ? QQmlBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()) : 0; - if (!newBinding) { - newBinding = new QQmlBinding(e->expression(), object(), qmlContext(this)); - newBinding->setSourceLocation(e->sourceFile(), e->lineNumber(), e->columnNumber()); - } + if (!newBinding) + newBinding = new QQmlBinding(e->expression(), false, object(), QQmlContextData::get(qmlContext(this)), + e->sourceFile(), e->lineNumber(), e->columnNumber()); newBinding->setTarget(prop); - a.toBinding = newBinding; + a.toBinding = QQmlAbstractBinding::getPointer(newBinding); a.deletableToBinding = true; } @@ -682,7 +681,7 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString } else { QQmlBinding *newBinding = new QQmlBinding(newExpression->expression(), object(), qmlContext(this)); newBinding->setTarget(d->property(name)); - action.toBinding = newBinding; + action.toBinding = QQmlAbstractBinding::getPointer(newBinding); action.deletableToBinding = true; state()->addEntryToRevertList(action); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index e3ad1e71cb..cca008eb0c 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -5045,7 +5045,7 @@ void tst_qqmlecmascript::functionAssignment_fromBinding() QQmlComponent component(&engine, testFileUrl("functionAssignment.1.qml")); QString url = component.url().toString(); - QString warning = url + ":4: Unable to assign a function to a property."; + QString warning = url + ":4:25: Unable to assign a function to a property."; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); MyQmlObject *o = qobject_cast(component.create()); @@ -5103,11 +5103,11 @@ void tst_qqmlecmascript::functionAssignmentfromJS_invalid() QVERIFY(!o->property("a").isValid()); QString url = component.url().toString(); - QString warning = url + ":67: Unable to assign QString to int"; + QString warning = url + ":67:17: Unable to assign QString to int"; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); o->setProperty("assignWrongType", true); - warning = url + ":71: Unable to assign QString to int"; + warning = url + ":71:29: Unable to assign QString to int"; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); o->setProperty("assignWrongTypeToValueType", true); diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index ae300900c9..5ef8937dc1 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -143,7 +143,7 @@ void tst_qqmlproperty::qmlmetaproperty() { QQmlProperty prop; - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -246,7 +246,7 @@ void tst_qqmlproperty::qmlmetaproperty_object() { QQmlProperty prop(&object); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -292,8 +292,8 @@ void tst_qqmlproperty::qmlmetaproperty_object() { QQmlProperty prop(&dobject); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -347,7 +347,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() { QQmlProperty prop(&object, QString("defaultProperty")); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -393,8 +393,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() { QQmlProperty prop(&dobject, QString("defaultProperty")); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -442,8 +442,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() { QQmlProperty prop(&dobject, QString("onClicked")); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -490,8 +490,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string() { QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged")); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -544,7 +544,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() { QQmlProperty prop(&object, engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -590,8 +590,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_context() { QQmlProperty prop(&dobject, engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -645,7 +645,7 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() { QQmlProperty prop(&object, QString("defaultProperty"), engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -691,8 +691,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() { QQmlProperty prop(&dobject, QString("defaultProperty"), engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -740,8 +740,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() { QQmlProperty prop(&dobject, QString("onClicked"), engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); @@ -788,8 +788,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context() { QQmlProperty prop(&dobject, QString("onPropertyWithNotifyChanged"), engine.rootContext()); - QWeakPointer binding(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())); - binding.data()->setTarget(prop); + QWeakPointer binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext()))); + static_cast(binding.data())->setTarget(prop); QVERIFY(binding != 0); QWeakPointer expression(new QQmlExpression()); QVERIFY(expression != 0); -- cgit v1.2.3 From 147247a31a9d6c1edadb0c7c78cf10b894dfab25 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Thu, 15 Mar 2012 10:20:26 +1000 Subject: Don't allow tst_QJSEngine or tst_QJSValue instance to be collected Both of those unit tests currently change the ownership of the test instance object, which could result in it being collected by the JS GC and deleted if events were processed. Change-Id: I5a9821fb56e19af1d52fea46e54755875dfbb29a Reviewed-by: Michael Brasser --- tests/auto/qml/qjsengine/tst_qjsengine.cpp | 24 +++++++++++++-------- tests/auto/qml/qjsvalue/tst_qjsvalue.cpp | 34 ++++++++++++++++++------------ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 66fef8e2dd..6f9cc93757 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -899,6 +899,7 @@ void tst_QJSEngine::jsParseDate() void tst_QJSEngine::newQObject() { QJSEngine eng; + QObject temp; { QJSValue qobject = eng.newQObject(0); @@ -907,11 +908,11 @@ void tst_QJSEngine::newQObject() QCOMPARE(qobject.toQObject(), (QObject *)0); } { - QJSValue qobject = eng.newQObject(this); + QJSValue qobject = eng.newQObject(&temp); QVERIFY(!qobject.isUndefined()); QCOMPARE(qobject.isQObject(), true); QCOMPARE(qobject.isObject(), true); - QCOMPARE(qobject.toQObject(), (QObject *)this); + QCOMPARE(qobject.toQObject(), (QObject *)&temp); QVERIFY(!qobject.isCallable()); // prototype should be QObject.prototype QCOMPARE(qobject.prototype().isObject(), true); @@ -1068,6 +1069,7 @@ void tst_QJSEngine::newQObject_sameQObject() #if 0 // FIXME: No prototype API in QScriptEngine void tst_QJSEngine::newQObject_defaultPrototype() { + QObject temp; QScriptEngine eng; // newQObject() should set the default prototype, if one has been registered { @@ -1076,14 +1078,14 @@ void tst_QJSEngine::newQObject_defaultPrototype() QScriptValue qobjectProto = eng.newObject(); eng.setDefaultPrototype(qMetaTypeId(), qobjectProto); { - QScriptValue ret = eng.newQObject(this); + QScriptValue ret = eng.newQObject(&temp); QVERIFY(ret.prototype().equals(qobjectProto)); } QScriptValue tstProto = eng.newObject(); int typeId = qRegisterMetaType("tst_QJSEngine*"); eng.setDefaultPrototype(typeId, tstProto); { - QScriptValue ret = eng.newQObject(this); + QScriptValue ret = eng.newQObject(temp); QVERIFY(ret.prototype().equals(tstProto)); } @@ -1261,7 +1263,8 @@ void tst_QJSEngine::newQMetaObject() QVERIFY(instanceofJS(inst, qclass3).strictlyEquals(false)); } { - QScriptValue inst = qclass4.callAsConstructor(QScriptValueList() << eng.newQObject(this)); + QObject temp; + QScriptValue inst = qclass4.callAsConstructor(QScriptValueList() << eng.newQObject(&temp)); QVERIFY(inst.isQObject()); QVERIFY(inst.toQObject() != 0); QCOMPARE(inst.toQObject()->parent(), (QObject*)this); @@ -2887,6 +2890,7 @@ void tst_QJSEngine::castWithPrototypeChain() QScriptEngine eng; Bar bar; Baz baz; + QObject temp; QScriptValue barProto = eng.toScriptValue(&bar); QScriptValue bazProto = eng.toScriptValue(&baz); eng.setDefaultPrototype(qMetaTypeId(), barProto); @@ -2954,7 +2958,7 @@ void tst_QJSEngine::castWithPrototypeChain() QVERIFY(pbar == 0); } - bazProto.setPrototype(eng.newQObject(this)); + bazProto.setPrototype(eng.newQObject(&temp)); { Baz *pbaz = qscriptvalue_cast(baz2Value); QVERIFY(pbaz != 0); @@ -3756,8 +3760,9 @@ private: QScriptEngine* m_engine; protected: void run() { + QObject temp; m_engine = new QScriptEngine(); - m_engine->setGlobalObject(m_engine->newQObject(this)); + m_engine->setGlobalObject(m_engine->newQObject(&temp)); m_engine->evaluate("while (1) { sleep(); }"); delete m_engine; } @@ -4941,6 +4946,7 @@ void tst_QJSEngine::reentrancy_Array() void tst_QJSEngine::reentrancy_objectCreation() { + QObject temp; QJSEngine eng1; QJSEngine eng2; { @@ -4957,8 +4963,8 @@ void tst_QJSEngine::reentrancy_objectCreation() QCOMPARE(qjsvalue_cast(r2), qjsvalue_cast(r1)); } { - QJSValue o1 = eng1.newQObject(this); - QJSValue o2 = eng2.newQObject(this); + QJSValue o1 = eng1.newQObject(&temp); + QJSValue o2 = eng2.newQObject(&temp); QCOMPARE(o1.toQObject(), o2.toQObject()); QCOMPARE(o2.toQObject(), o1.toQObject()); } diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index cec10ccf38..ad655217ad 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -986,6 +986,7 @@ Q_DECLARE_METATYPE(QVariant) void tst_QJSValue::toVariant() { QJSEngine eng; + QObject temp; QJSValue undefined = eng.toScriptValue(QVariant()); QCOMPARE(undefined.toVariant(), QVariant()); @@ -1020,11 +1021,11 @@ void tst_QJSValue::toVariant() QJSValue object = eng.newObject(); QCOMPARE(object.toVariant(), QVariant(QVariantMap())); - QJSValue qobject = eng.newQObject(this); + QJSValue qobject = eng.newQObject(&temp); { QVariant var = qobject.toVariant(); QCOMPARE(var.userType(), int(QMetaType::QObjectStar)); - QCOMPARE(qVariantValue(var), (QObject *)this); + QCOMPARE(qVariantValue(var), (QObject *)&temp); } { @@ -1130,10 +1131,11 @@ Q_DECLARE_METATYPE(QPushButton*); void tst_QJSValue::toQObject() { QJSEngine eng; + QObject temp; - QJSValue qobject = eng.newQObject(this); - QCOMPARE(qobject.toQObject(), (QObject *)this); - QCOMPARE(qjsvalue_cast(qobject), (QObject *)this); + QJSValue qobject = eng.newQObject(&temp); + QCOMPARE(qobject.toQObject(), (QObject *)&temp); + QCOMPARE(qjsvalue_cast(qobject), (QObject *)&temp); QCOMPARE(qjsvalue_cast(qobject), (QWidget *)0); QWidget widget; @@ -2168,6 +2170,7 @@ void tst_QJSValue::getSetData_objects_data() { #if 0 // FIXME: no setData/data API newEngine(); + QObject *temp = new QObject; QTest::addColumn("object"); @@ -2175,7 +2178,7 @@ void tst_QJSValue::getSetData_objects_data() QTest::newRow("object from engine") << engine->newObject(); QTest::newRow("Array") << engine->newArray(); QTest::newRow("Date") << engine->evaluate("new Date(12324)"); - QTest::newRow("QObject") << engine->newQObject(this); + QTest::newRow("QObject") << engine->newQObject(temp); QTest::newRow("RegExp") << engine->newRegExp(QRegExp()); #endif } @@ -2265,6 +2268,7 @@ public: void tst_QJSValue::getSetScriptClass_emptyClass_data() { newEngine(); + QObject *temp = new QObject; QTest::addColumn("value"); QTest::newRow("invalid") << QJSValue(); @@ -2281,7 +2285,7 @@ void tst_QJSValue::getSetScriptClass_emptyClass_data() QTest::newRow("undefined") << QJSValue(engine->toScriptValue(QVariant())); QTest::newRow("object") << QJSValue(engine->newObject()); QTest::newRow("date") << QJSValue(engine->evaluate("new Date()")); - QTest::newRow("qobject") << QJSValue(engine->newQObject(this)); + QTest::newRow("qobject") << QJSValue(engine->newQObject(temp)); } void tst_QJSValue::getSetScriptClass_emptyClass() @@ -2341,9 +2345,10 @@ void tst_QJSValue::getSetScriptClass_QVariant() void tst_QJSValue::getSetScriptClass_QObject() { QScriptEngine eng; + QObject temp; TestScriptClass testClass(&eng); { - QJSValue obj = eng.newQObject(this); + QJSValue obj = eng.newQObject(&temp); QVERIFY(obj.isQObject()); obj.setScriptClass(&testClass); QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass); @@ -2999,6 +3004,7 @@ void tst_QJSValue::lessThan() void tst_QJSValue::equals() { QJSEngine eng; + QObject temp; QVERIFY(QJSValue().equals(QJSValue())); @@ -3088,8 +3094,8 @@ void tst_QJSValue::equals() QCOMPARE(obj1.equals(obj1), true); QCOMPARE(obj2.equals(obj2), true); - QJSValue qobj1 = eng.newQObject(this); - QJSValue qobj2 = eng.newQObject(this); + QJSValue qobj1 = eng.newQObject(&temp); + QJSValue qobj2 = eng.newQObject(&temp); QJSValue qobj3 = eng.newQObject(0); // FIXME: No ScriptOwnership: QJSValue qobj4 = eng.newQObject(new QObject(), QScriptEngine::ScriptOwnership); @@ -3137,6 +3143,7 @@ void tst_QJSValue::equals() void tst_QJSValue::strictlyEquals() { QJSEngine eng; + QObject temp; QVERIFY(QJSValue().strictlyEquals(QJSValue())); @@ -3242,8 +3249,8 @@ void tst_QJSValue::strictlyEquals() QCOMPARE(obj2.strictlyEquals(obj2), true); QVERIFY(!obj1.strictlyEquals(QJSValue())); - QJSValue qobj1 = eng.newQObject(this); - QJSValue qobj2 = eng.newQObject(this); + QJSValue qobj1 = eng.newQObject(&temp); + QJSValue qobj2 = eng.newQObject(&temp); QVERIFY(qobj1.strictlyEquals(qobj2)); { @@ -3482,13 +3489,14 @@ void tst_QJSValue::prettyPrinter() void tst_QJSValue::engineDeleted() { QJSEngine *eng = new QJSEngine; + QObject temp; QJSValue v1 = eng->toScriptValue(123); QVERIFY(v1.isNumber()); QJSValue v2 = eng->toScriptValue(QString("ciao")); QVERIFY(v2.isString()); QJSValue v3 = eng->newObject(); QVERIFY(v3.isObject()); - QJSValue v4 = eng->newQObject(this); + QJSValue v4 = eng->newQObject(&temp); QVERIFY(v4.isQObject()); QJSValue v5 = "Hello"; QVERIFY(v2.isString()); -- cgit v1.2.3 From 25793276e52240e4dfad297dc5b9eb282ed3f5e6 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Tue, 13 Mar 2012 13:30:39 +1000 Subject: Fix crash caused by dereferencing collected v8 data If a var property of a QObject is read after the v8 data associated with the qobject has been deleted but prior to the DeferredDelete event being processed, the varProperties array will be null and a crash will occur. This patch ensures that we check for this condition in both the access and set codepaths for var properties, and also ensures that an object which has previously been queued for deletion cannot be referenced in JS. Finally, it adds a unit test to ensure that we don't regress. Task-number: QTBUG-24748 Change-Id: Idde384ca01e18f4dcf9e376e9379f2c5eb410e14 Reviewed-by: Michael Brasser --- src/qml/qml/qqmldata_p.h | 7 +++--- src/qml/qml/qqmlvmemetaobject.cpp | 25 +++++++++++++------ src/qml/qml/qqmlvmemetaobject_p.h | 2 +- src/qml/qml/v8/qv8qobjectwrapper.cpp | 9 +++++-- .../qqmlecmascript/data/ComponentWithVarProp.qml | 5 ++++ .../qqmlecmascript/data/propertyVarOwnership.5.qml | 28 ++++++++++++++++++++++ tests/auto/qml/qqmlecmascript/testtypes.h | 8 ++++++- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 9 +++++++ 8 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 tests/auto/qml/qqmlecmascript/data/ComponentWithVarProp.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.5.qml diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index e4ba44583d..09d1a23510 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -78,8 +78,8 @@ class Q_QML_EXPORT QQmlData : public QAbstractDeclarativeData public: QQmlData() : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), - hasTaintedV8Object(false), notifyList(0), context(0), outerContext(0), bindings(0), - nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), + hasTaintedV8Object(false), isQueuedForDeletion(false), notifyList(0), context(0), outerContext(0), + bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), v8objectid(0), propertyCache(0), guards(0), extendedData(0) { init(); @@ -110,7 +110,8 @@ public: quint32 indestructible:1; quint32 explicitIndestructibleSet:1; quint32 hasTaintedV8Object:1; - quint32 dummy:27; + quint32 isQueuedForDeletion:1; + quint32 dummy:26; struct NotifyList { quint64 connectionMask; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index ecfde203c6..cc4ba091ce 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -832,15 +832,17 @@ v8::Handle QQmlVMEMetaObject::readVarProperty(int id) { Q_ASSERT(id >= firstVarPropertyIndex); - ensureVarPropertiesAllocated(); - return varProperties->Get(id - firstVarPropertyIndex); + if (ensureVarPropertiesAllocated()) + return varProperties->Get(id - firstVarPropertyIndex); + return v8::Handle(); } QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) { if (id >= firstVarPropertyIndex) { - ensureVarPropertiesAllocated(); - return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(varProperties->Get(id - firstVarPropertyIndex), -1); + if (ensureVarPropertiesAllocated()) + return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(varProperties->Get(id - firstVarPropertyIndex), -1); + return QVariant(); } else { if (data[id].dataType() == QMetaType::QObjectStar) { return QVariant::fromValue(data[id].asQObject()); @@ -853,7 +855,8 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle value) { Q_ASSERT(id >= firstVarPropertyIndex); - ensureVarPropertiesAllocated(); + if (!ensureVarPropertiesAllocated()) + return; // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. @@ -882,7 +885,8 @@ void QQmlVMEMetaObject::writeVarProperty(int id, v8::Handle value) void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) { if (id >= firstVarPropertyIndex) { - ensureVarPropertiesAllocated(); + if (!ensureVarPropertiesAllocated()) + return; // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. @@ -1029,10 +1033,17 @@ void QQmlVMEMetaObject::setVMEProperty(int index, v8::Handle v) return writeVarProperty(index - propOffset, v); } -void QQmlVMEMetaObject::ensureVarPropertiesAllocated() +bool QQmlVMEMetaObject::ensureVarPropertiesAllocated() { if (!varPropertiesInitialized) allocateVarPropertiesArray(); + + // in some situations, the QObject's v8object (and associated v8 data, + // such as the varProperties array) will have been cleaned up, but the + // QObject ptr will not yet have been deleted (eg, waiting on deleteLater). + // In this situation, the varProperties handle will be (and should remain) + // empty. + return !varProperties.IsEmpty(); } // see also: QV8GCCallback::garbageCollectorPrologueCallback() diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 84c88fdd7b..1b5ceb8203 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -195,7 +195,7 @@ private: static void VarPropertiesWeakReferenceCallback(v8::Persistent object, void* parameter); static void GcPrologueCallback(QV8GCCallback::Node *node); inline void allocateVarPropertiesArray(); - inline void ensureVarPropertiesAllocated(); + inline bool ensureVarPropertiesAllocated(); void connectAlias(int aliasId); QBitArray aConnected; diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index a483346dd1..3faea2c97b 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -883,8 +883,10 @@ static void WeakQObjectReferenceCallback(v8::Persistent handle, void QQmlData *ddata = QQmlData::get(object, false); if (ddata) { ddata->v8object.Clear(); - if (!object->parent() && !ddata->indestructible) + if (!object->parent() && !ddata->indestructible) { + ddata->isQueuedForDeletion = true; object->deleteLater(); + } } } @@ -1043,12 +1045,15 @@ v8::Handle QV8QObjectWrapper::newQObject(QObject *object) if (QObjectPrivate::get(object)->wasDeleted) return v8::Null(); - + QQmlData *ddata = QQmlData::get(object, true); if (!ddata) return v8::Undefined(); + if (ddata->isQueuedForDeletion) + return v8::Null(); + if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) { // We own the v8object return v8::Local::New(ddata->v8object); diff --git a/tests/auto/qml/qqmlecmascript/data/ComponentWithVarProp.qml b/tests/auto/qml/qqmlecmascript/data/ComponentWithVarProp.qml new file mode 100644 index 0000000000..3105b8c79f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/ComponentWithVarProp.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property var varprop: true +} diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.5.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.5.qml new file mode 100644 index 0000000000..ad5807b1cf --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/propertyVarOwnership.5.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 +import Qt.test 1.0 as ModuleApi + +Item { + id: testOwnership + property bool test: false + + function runTest() { + var o; + var c = Qt.createComponent("ComponentWithVarProp.qml"); + if (c.status == Component.Ready) { + o = c.createObject(); + } else { + return; // failed to create component. + } + o.varprop = true; // causes initialization of varProperties. + ModuleApi.trackObject(o); // stores QObject ptr + if (ModuleApi.trackedObject() == null) return; // is still valid, should have a valid v8object. + o = new Date(); // causes object to be gc-able. + gc(); // collect object's v8object + varProperties, queues deleteLater. + if (ModuleApi.trackedObject() != null) return; // v8object was previously collected. + ModuleApi.setTrackedObjectProperty("varprop"); // deferences varProperties of object. + test = !(ModuleApi.trackedObjectProperty("varprop")); // deferences varProperties of object. + // if we didn't crash, success. + } +} + + diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 65b84d66cb..54fab26405 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -982,7 +982,7 @@ class testQObjectApi : public QObject public: testQObjectApi(QObject* parent = 0) - : QObject(parent), m_testProperty(0), m_testWritableProperty(0), m_testWritableFinalProperty(0), m_methodCallCount(0) + : QObject(parent), m_testProperty(0), m_testWritableProperty(0), m_testWritableFinalProperty(0), m_methodCallCount(0), m_trackedObject(0) { } @@ -992,6 +992,11 @@ public: Q_INVOKABLE int qobjectEnumTestMethod(MyEnum val) { return (static_cast(val) + 5); } Q_INVOKABLE int qobjectTestMethod(int increment = 1) { m_methodCallCount += increment; return m_methodCallCount; } + Q_INVOKABLE void trackObject(QObject *obj) { m_trackedObject = obj; } + Q_INVOKABLE QObject *trackedObject() const { return m_trackedObject; } + Q_INVOKABLE void setTrackedObjectProperty(const QString &propName) const { m_trackedObject->setProperty(qPrintable(propName), QVariant(5)); } + Q_INVOKABLE QVariant trackedObjectProperty(const QString &propName) const { return m_trackedObject->property(qPrintable(propName)); } + int qobjectTestProperty() const { return m_testProperty; } void setQObjectTestProperty(int tp) { m_testProperty = tp; emit qobjectTestPropertyChanged(tp); } @@ -1011,6 +1016,7 @@ private: int m_testWritableProperty; int m_testWritableFinalProperty; int m_methodCallCount; + QObject *m_trackedObject; }; class CircularReferenceObject : public QObject, diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index cca008eb0c..3bbbc2c79c 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3906,6 +3906,15 @@ void tst_qqmlecmascript::propertyVarOwnership() delete object; } + // Garbage collection cannot result in attempted dereference of empty handle + { + QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.5.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QMetaObject::invokeMethod(object, "runTest"); + QCOMPARE(object->property("test").toBool(), true); + delete object; + } } void tst_qqmlecmascript::propertyVarImplicitOwnership() -- cgit v1.2.3 From d7f2a77f2b236de6b08b4c8905722280d9c44541 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 14 Mar 2012 16:56:46 +1000 Subject: Set more sensible Flickable default input filtering parameters Shouldn't throw anything away by default. Also fix bug that flicking back into bounds from outside bounds halved velocity. Change-Id: I3c2d303a9e46910439dc8bfb01771376f634a684 Reviewed-by: Laszlo Agocs Reviewed-by: Michael Brasser --- src/quick/items/qquickflickable.cpp | 8 ++++---- tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 2447fd6ed1..b6d3ebd7f2 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE // The number of samples to discard when calculating the flick velocity. // Touch panels often produce inaccurate results as the finger is lifted. #ifndef QML_FLICK_DISCARDSAMPLES -#define QML_FLICK_DISCARDSAMPLES 1 +#define QML_FLICK_DISCARDSAMPLES 0 #endif // The default maximum velocity of a flick. @@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE // FlickThreshold determines how far the "mouse" must have moved // before we perform a flick. -static const int FlickThreshold = 20; +static const int FlickThreshold = 15; // RetainGrabVelocity is the maxmimum instantaneous velocity that // will ensure the Flickable retains the grab on consecutive flicks. @@ -1030,7 +1030,7 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) vVelocity = (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) ? extended->velocity().y() : vData.velocity; } - if (vData.atBeginning || vData.atEnd) { + if ((vData.atBeginning && vVelocity > 0.) || (vData.atEnd && vVelocity < 0.)) { vVelocity /= 2; } else if (vData.continuousFlickVelocity != 0.0 && vData.viewSize/q->height() > QML_FLICK_MULTIFLICK_RATIO @@ -1046,7 +1046,7 @@ void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) hVelocity = (extended && extended->capabilities().testFlag(QTouchDevice::Velocity)) ? extended->velocity().x() : hData.velocity; } - if (hData.atBeginning || hData.atEnd) { + if ((hData.atBeginning && hVelocity > 0.) || (hData.atEnd && hVelocity < 0.)) { hVelocity /= 2; } else if (hData.continuousFlickVelocity != 0.0 && hData.viewSize/q->width() > QML_FLICK_MULTIFLICK_RATIO diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index a2ecadf33a..4b157a434b 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -585,7 +585,7 @@ void tst_qquickflickable::flickVelocity() QQuickFlickablePrivate *fp = QQuickFlickablePrivate::get(flickable); bool boosted = false; for (int i = 0; i < 6; ++i) { - flick(canvas, QPoint(20,390), QPoint(20, 50), 200); + flick(canvas, QPoint(20,390), QPoint(20, 50), 100); boosted |= fp->flickBoost > 1.0; } QVERIFY(boosted); -- cgit v1.2.3 From 1c7b0362b8a1d230e52b7ee5df2aa36a3217b79b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 15 Mar 2012 15:55:24 +1000 Subject: Don't leak function objects created by VisualDataModel. Function objects created from a FunctionTemplate are not short lived, and the objects created by a VisualDataModel can change between instances meaning a template is needed per instance. So use an object template as a constructor instead of a function. Change-Id: I364c6e4f714a623b7adb7475a3ee9862eeeeb119 Reviewed-by: Martin Jones --- src/quick/items/qquickvisualadaptormodel.cpp | 24 ++++++++++++------------ src/quick/items/qquickvisualdatamodel.cpp | 18 +++++++++--------- src/quick/items/qquickvisualdatamodel_p_p.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/quick/items/qquickvisualadaptormodel.cpp b/src/quick/items/qquickvisualadaptormodel.cpp index fb85810984..622adf4ce9 100644 --- a/src/quick/items/qquickvisualadaptormodel.cpp +++ b/src/quick/items/qquickvisualadaptormodel.cpp @@ -173,7 +173,7 @@ public: VDMDelegateDataType *m_delegateDataType; CreateModelData createItem; StringValue stringValue; - v8::Persistent m_constructor; + v8::Persistent m_constructor; int m_ref; int m_count; @@ -716,9 +716,9 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() v8::HandleScope handleScope; v8::Context::Scope contextScope(v8Engine->context()); - v8::Local ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->SetAccessor( + v8::Local constructor = v8::ObjectTemplate::New(); + constructor->SetHasExternalResource(true); + constructor->SetAccessor( v8::String::New("index"), QQuickVisualDataModelItemMetaObject::get_index); if (m_listAccessor @@ -726,9 +726,9 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() && m_listAccessor->type() != QQuickListAccessor::Instance) { createItem = &QQuickVDMListAccessorData::create; stringValue = &QQuickVDMListAccessorData::stringValue; - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8::String::New("modelData"), QQuickVDMListAccessorData::get_modelData); - m_constructor = qPersistentNew(ft->GetFunction()); + m_constructor = qPersistentNew(constructor); return; } @@ -741,7 +741,7 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() const QString roleName = m_listModelInterface->toString(role); const QByteArray propertyName = roleName.toUtf8(); addProperty(role, propertyId, propertyName, "QVariant"); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8Engine->toString(roleName), QQuickVDMListModelInterfaceData::get_property, QQuickVDMListModelInterfaceData::set_property, @@ -751,7 +751,7 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() m_roleCount = m_propertyData.count(); if (m_propertyData.count() == 1) { addProperty(roles.first(), 1, "modelData", "QVariant", true); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8::String::New("modelData"), QQuickVDMListModelInterfaceData::get_property, QQuickVDMListModelInterfaceData::set_property, @@ -764,7 +764,7 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() for (QHash::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) { const int propertyId = m_propertyData.count(); addProperty(it.key(), propertyId, it.value(), "QVariant"); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8::String::New(it.value().constData(), it.value().length()), QQuickVDMAbstractItemModelData::get_property, QQuickVDMAbstractItemModelData::set_property, @@ -774,14 +774,14 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() m_roleCount = m_propertyData.count(); if (m_propertyData.count() == 1) { addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8::String::New("modelData"), QQuickVDMAbstractItemModelData::get_property, QQuickVDMAbstractItemModelData::set_property, v8::Int32::New(0)); m_roleNames.insert("modelData", roleNames.begin().key()); } - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( v8::String::New("hasModelChildren"), QQuickVDMAbstractItemModelData::get_hasModelChildren); } else if (m_listAccessor) { @@ -796,7 +796,7 @@ void QQuickVisualAdaptorModelPrivate::createMetaObject() if (!m_objectList) { m_delegateDataType->propertyCache = new QQmlPropertyCache( m_engine, m_delegateDataType->metaObject); - m_constructor = qPersistentNew(ft->GetFunction()); + m_constructor = qPersistentNew(constructor); } } diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 97d137202a..88d46c60ee 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -1306,11 +1306,13 @@ QQuickVisualDataModelItemMetaType::QQuickVisualDataModelItemMetaType( v8::HandleScope handleScope; v8::Context::Scope contextScope(engine->context()); - v8::Local ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->SetAccessor(v8::String::New("model"), get_model); - ft->PrototypeTemplate()->SetAccessor(v8::String::New("groups"), get_groups, set_groups); - ft->PrototypeTemplate()->SetAccessor(v8::String::New("isUnresolved"), get_member, 0, v8::Int32::New(30)); + + constructor = qPersistentNew(v8::ObjectTemplate::New()); + + constructor->SetHasExternalResource(true); + constructor->SetAccessor(v8::String::New("model"), get_model); + constructor->SetAccessor(v8::String::New("groups"), get_groups, set_groups); + constructor->SetAccessor(v8::String::New("isUnresolved"), get_member, 0, v8::Int32::New(30)); int notifierId = 0; for (int i = 0; i < groupNames.count(); ++i, ++notifierId) { @@ -1321,7 +1323,7 @@ QQuickVisualDataModelItemMetaType::QQuickVisualDataModelItemMetaType( propertyName.toUtf8(), "bool", notifierId); propertyBuilder.setWritable(true); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( engine->toString(propertyName), get_member, set_member, v8::Int32::New(i + 1)); } for (int i = 0; i < groupNames.count(); ++i, ++notifierId) { @@ -1331,13 +1333,11 @@ QQuickVisualDataModelItemMetaType::QQuickVisualDataModelItemMetaType( propertyName.toUtf8(), "int", notifierId); propertyBuilder.setWritable(true); - ft->PrototypeTemplate()->SetAccessor( + constructor->SetAccessor( engine->toString(propertyName), get_index, 0, v8::Int32::New(i + 1)); } metaObject = builder.toMetaObject(); - - constructor = qPersistentNew(ft->GetFunction()); } QQuickVisualDataModelItemMetaType::~QQuickVisualDataModelItemMetaType() diff --git a/src/quick/items/qquickvisualdatamodel_p_p.h b/src/quick/items/qquickvisualdatamodel_p_p.h index c53ed5bdbb..c2db04511d 100644 --- a/src/quick/items/qquickvisualdatamodel_p_p.h +++ b/src/quick/items/qquickvisualdatamodel_p_p.h @@ -92,7 +92,7 @@ public: QV8Engine * const v8Engine; QMetaObject *metaObject; const QStringList groupNames; - v8::Persistent constructor; + v8::Persistent constructor; }; class QQuickVisualAdaptorModel; -- cgit v1.2.3 From 67f589209dc856be3ac6261f51023125343812ce Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 12 Mar 2012 18:48:05 +1000 Subject: Don't assert if focus is already clear. Already cleared focus should exit the function without terminating the runtime. Task-number: QTBUG-24714 Change-Id: Ia8c6be0d88e43d1f71112acc7bac3eb674f22de8 Reviewed-by: Martin Jones --- src/quick/items/qquickcanvas.cpp | 8 ++++++-- .../auto/quick/qquickitem/data/multipleFocusClears.qml | 18 ++++++++++++++++++ tests/auto/quick/qquickitem/tst_qquickitem.cpp | 11 +++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/auto/quick/qquickitem/data/multipleFocusClears.qml diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 26360229e9..a6c2a90407 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -607,7 +607,6 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, { Q_Q(QQuickCanvas); - Q_UNUSED(item); Q_ASSERT(item); Q_ASSERT(scope || item == rootItem); @@ -618,7 +617,12 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, qWarning() << " activeFocusItem:" << (QObject *)activeFocusItem; #endif - QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0; + QQuickItemPrivate *scopePrivate = 0; + if (scope) { + scopePrivate = QQuickItemPrivate::get(scope); + if ( !scopePrivate->subFocusItem ) + return;//No focus, nothing to do. + } QQuickItem *oldActiveFocusItem = 0; QQuickItem *newActiveFocusItem = 0; diff --git a/tests/auto/quick/qquickitem/data/multipleFocusClears.qml b/tests/auto/quick/qquickitem/data/multipleFocusClears.qml new file mode 100644 index 0000000000..f68a8901ab --- /dev/null +++ b/tests/auto/quick/qquickitem/data/multipleFocusClears.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 + +Rectangle { + width: 200 + height: 200 + + FocusScope { + id: focusScope + anchors.fill: parent + + TextInput { + anchors.centerIn: parent + text: "Some text" + onActiveFocusChanged: if (!activeFocus) focusScope.focus = false + Component.onCompleted: forceActiveFocus() + } + } +} diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 7a589a48cd..9fdfa78559 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -138,6 +138,7 @@ private slots: void scopedFocus(); void addedToCanvas(); void changeParent(); + void multipleFocusClears(); void constructor(); void setParentItem(); @@ -675,6 +676,16 @@ void tst_qquickitem::changeParent() } +void tst_qquickitem::multipleFocusClears() +{ + //Multiple clears of focus inside a focus scope shouldn't crash. QTBUG-24714 + QQuickView *view = new QQuickView; + view->setSource(testFileUrl("multipleFocusClears.qml")); + view->show(); + ensureFocus(view); + QTRY_VERIFY(QGuiApplication::focusWindow() == view); +} + void tst_qquickitem::constructor() { QQuickItem *root = new QQuickItem; -- cgit v1.2.3 From 1c8e65a0999c81d2252757f8872c663417270d37 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 12 Mar 2012 12:56:12 +1000 Subject: Fix merge Examples are in quick, not qtquick, since the rename merge. Change-Id: Ideb677752c3ea320bbddba49204d37e8a34e2609 Reviewed-by: Matthew Vogt --- .../qtquick/mousearea/mousearea-wheel-example.qml | 84 ---------------------- .../quick/mousearea/mousearea-wheel-example.qml | 84 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 84 deletions(-) delete mode 100644 examples/qtquick/mousearea/mousearea-wheel-example.qml create mode 100644 examples/quick/mousearea/mousearea-wheel-example.qml diff --git a/examples/qtquick/mousearea/mousearea-wheel-example.qml b/examples/qtquick/mousearea/mousearea-wheel-example.qml deleted file mode 100644 index 60cfb166f8..0000000000 --- a/examples/qtquick/mousearea/mousearea-wheel-example.qml +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - height: 700 - width: 485 - color: "#333333" - - Column { - anchors.centerIn: parent - spacing: 2 - - Repeater { - model: ["#9ACD32", "#EEEEEE", "#FFD700", "#87CEEB"] - - Rectangle { - property real scaleFactor: 1 - - height: 40 * scaleFactor - width: 60 * scaleFactor - color: modelData - anchors.horizontalCenter: parent.horizontalCenter - - MouseArea { - anchors.fill: parent - onWheel: { - if (wheel.modifiers & Qt.ControlModifier) { - if (wheel.angleDelta.y > 0) - parent.scaleFactor += 0.2; - else if (parent.scaleFactor - 0.2 >= 0.2) - parent.scaleFactor -= 0.2; - } - } - } - } - } - } - - Text { - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - color: "#FFD700" - text: "Rotate the mouse wheel pressing to resize the squares." - } -} diff --git a/examples/quick/mousearea/mousearea-wheel-example.qml b/examples/quick/mousearea/mousearea-wheel-example.qml new file mode 100644 index 0000000000..60cfb166f8 --- /dev/null +++ b/examples/quick/mousearea/mousearea-wheel-example.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + height: 700 + width: 485 + color: "#333333" + + Column { + anchors.centerIn: parent + spacing: 2 + + Repeater { + model: ["#9ACD32", "#EEEEEE", "#FFD700", "#87CEEB"] + + Rectangle { + property real scaleFactor: 1 + + height: 40 * scaleFactor + width: 60 * scaleFactor + color: modelData + anchors.horizontalCenter: parent.horizontalCenter + + MouseArea { + anchors.fill: parent + onWheel: { + if (wheel.modifiers & Qt.ControlModifier) { + if (wheel.angleDelta.y > 0) + parent.scaleFactor += 0.2; + else if (parent.scaleFactor - 0.2 >= 0.2) + parent.scaleFactor -= 0.2; + } + } + } + } + } + } + + Text { + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + color: "#FFD700" + text: "Rotate the mouse wheel pressing to resize the squares." + } +} -- cgit v1.2.3 From b634c19680cd1d4dd925a18e616844ed420d18ae Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 14 Mar 2012 16:11:10 +0100 Subject: Support for multiple textures in the default distance field glyph cache. The default implementation of the distance field glyph cache can now store the glyphs of one font in several textures, allowing to cache more glyphs at once. The default maximum number of textures per cache is 3. Glyphs are recycled when all textures are full. Change-Id: I28d2d6cf5aa409141e2700b505023f15d3c2cd26 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qsgdefaultdistancefieldglyphcache.cpp | 86 +++++++++++++--------- .../qsgdefaultdistancefieldglyphcache_p.h | 59 +++++++++++---- 2 files changed, 94 insertions(+), 51 deletions(-) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 05d076ec1e..5864f35060 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -62,6 +62,7 @@ QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDefaultDistanceF QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) : QSGDistanceFieldGlyphCache(man, c, font) , m_maxTextureSize(0) + , m_maxTextureCount(3) { m_textureData = textureData(c); } @@ -77,25 +78,32 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet &glyph if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty()) continue; + if (textureIsFull(m_textureData->currentTexture) && m_textureData->textures.count() < m_maxTextureCount) + m_textureData->currentTexture = m_textureData->addTexture(); + m_textureData->unusedGlyphs.remove(glyphIndex); + DistanceFieldTextureData::TextureInfo *tex = m_textureData->currentTexture; + GlyphPosition p; p.glyph = glyphIndex; - p.position = QPointF(m_textureData->currX, m_textureData->currY); + p.position = QPointF(tex->currX, tex->currY); if (!cacheIsFull()) { - m_textureData->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()); - if (m_textureData->currX >= maxTextureSize()) { - m_textureData->currX = 0; - m_textureData->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()); + tex->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()); + if (tex->currX >= maxTextureSize()) { + tex->currX = 0; + tex->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()); } } else { // Recycle glyphs if (!m_textureData->unusedGlyphs.isEmpty()) { glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin(); TexCoord unusedCoord = glyphTexCoord(unusedGlyph); + tex = m_textureData->glyphsTexture.value(unusedGlyph); p.position = QPointF(unusedCoord.x, unusedCoord.y); m_textureData->unusedGlyphs.remove(unusedGlyph); + m_textureData->glyphsTexture.remove(unusedGlyph); removeGlyph(unusedGlyph); } } @@ -103,6 +111,7 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet &glyph if (p.position.y() < maxTextureSize()) { glyphPositions.append(p); glyphsToRender.append(glyphIndex); + m_textureData->glyphsTexture.insert(glyphIndex, tex); } } @@ -114,41 +123,46 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash { int requiredWidth = maxTextureSize(); int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default.. - int requiredHeight = qMin(maxTextureSize(), - qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()), - QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows)); - - resizeTexture((requiredWidth), (requiredHeight)); - glBindTexture(GL_TEXTURE_2D, m_textureData->texture); - QVector glyphTextures; + QHash > glyphTextures; QHash::const_iterator it; for (it = glyphs.constBegin(); it != glyphs.constEnd(); ++it) { glyph_t glyphIndex = it.key(); TexCoord c = glyphTexCoord(glyphIndex); + DistanceFieldTextureData::TextureInfo *texInfo = m_textureData->glyphsTexture.value(glyphIndex); - glyphTextures.append(glyphIndex); + int requiredHeight = qMin(maxTextureSize(), + qMax(texInfo->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()), + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows)); + + resizeTexture(texInfo, requiredWidth, requiredHeight); + glBindTexture(GL_TEXTURE_2D, texInfo->texture); + + glyphTextures[texInfo].append(glyphIndex); QImage glyph = it.value(); if (useWorkaroundBrokenFBOReadback()) { uchar *inBits = glyph.scanLine(0); - uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x); + uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x); for (int y = 0; y < glyph.height(); ++y) { qMemCopy(outBits, inBits, glyph.width()); inBits += glyph.bytesPerLine(); - outBits += m_textureData->image.bytesPerLine(); + outBits += texInfo->image.bytesPerLine(); } } glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits()); } - Texture t; - t.textureId = m_textureData->texture; - t.size = m_textureData->size; - setGlyphsTexture(glyphTextures, t); + QHash >::const_iterator i; + for (i = glyphTextures.constBegin(); i != glyphTextures.constEnd(); ++i) { + Texture t; + t.textureId = i.key()->texture; + t.size = i.key()->size; + setGlyphsTexture(i.value(), t); + } } void QSGDefaultDistanceFieldGlyphCache::referenceGlyphs(const QSet &glyphs) @@ -161,15 +175,15 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet &glyph m_textureData->unusedGlyphs += glyphs; } -void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height) +void QSGDefaultDistanceFieldGlyphCache::createTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height) { - if (useWorkaroundBrokenFBOReadback() && m_textureData->image.isNull()) - m_textureData->image = QImage(width, height, QImage::Format_Indexed8); + if (useWorkaroundBrokenFBOReadback() && texInfo->image.isNull()) + texInfo->image = QImage(width, height, QImage::Format_Indexed8); while (glGetError() != GL_NO_ERROR) { } - glGenTextures(1, &m_textureData->texture); - glBindTexture(GL_TEXTURE_2D, m_textureData->texture); + glGenTextures(1, &texInfo->texture); + glBindTexture(GL_TEXTURE_2D, texInfo->texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -177,35 +191,35 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - m_textureData->size = QSize(width, height); + texInfo->size = QSize(width, height); GLuint error = glGetError(); if (error != GL_NO_ERROR) { glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &m_textureData->texture); - m_textureData->texture = 0; + glDeleteTextures(1, &texInfo->texture); + texInfo->texture = 0; } } -void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height) +void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height) { - int oldWidth = m_textureData->size.width(); - int oldHeight = m_textureData->size.height(); + int oldWidth = texInfo->size.width(); + int oldHeight = texInfo->size.height(); if (width == oldWidth && height == oldHeight) return; - GLuint oldTexture = m_textureData->texture; - createTexture(width, height); + GLuint oldTexture = texInfo->texture; + createTexture(texInfo, width, height); if (!oldTexture) return; - updateTexture(oldTexture, m_textureData->texture, m_textureData->size); + updateTexture(oldTexture, texInfo->texture, texInfo->size); if (useWorkaroundBrokenFBOReadback()) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, m_textureData->image.constBits()); - m_textureData->image = m_textureData->image.copy(0, 0, width, height); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, texInfo->image.constBits()); + texInfo->image = texInfo->image.copy(0, 0, width, height); glDeleteTextures(1, &oldTexture); return; } @@ -267,7 +281,7 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height) glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, m_textureData->texture); + glBindTexture(GL_TEXTURE_2D, texInfo->texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index 76e4a64e60..12bbcce060 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -59,37 +59,55 @@ public: void referenceGlyphs(const QSet &glyphs); void releaseGlyphs(const QSet &glyphs); - bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); } + bool cacheIsFull() const { + return m_textureData->textures.count() == m_maxTextureCount + && textureIsFull(m_textureData->currentTexture); + } bool useWorkaroundBrokenFBOReadback() const; int maxTextureSize() const; -private: - void createTexture(int width, int height); - void resizeTexture(int width, int height); + void setMaxTextureCount(int max) { m_maxTextureCount = max; } + int maxTextureCount() const { return m_maxTextureCount; } +private: mutable int m_maxTextureSize; + int m_maxTextureCount; struct DistanceFieldTextureData : public QOpenGLSharedResource { - GLuint texture; + struct TextureInfo { + GLuint texture; + QSize size; + int currX; + int currY; + QImage image; + + TextureInfo() : texture(0), currX(0), currY(0) + { } + }; + + TextureInfo *currentTexture; + QList textures; + QHash glyphsTexture; GLuint fbo; - QSize size; QSet unusedGlyphs; - int currX; - int currY; - QImage image; QOpenGLShaderProgram *blitProgram; GLfloat blitVertexCoordinateArray[8]; GLfloat blitTextureCoordinateArray[8]; + TextureInfo *addTexture() + { + textures.append(TextureInfo()); + return &textures.last(); + } + DistanceFieldTextureData(QOpenGLContext *ctx) : QOpenGLSharedResource(ctx->shareGroup()) - , texture(0) , fbo(0) - , currX(0) - , currY(0) , blitProgram(0) { + currentTexture = addTexture(); + blitVertexCoordinateArray[0] = -1.0f; blitVertexCoordinateArray[1] = -1.0f; blitVertexCoordinateArray[2] = 1.0f; @@ -111,19 +129,26 @@ private: void invalidateResource() { - texture = 0; + glyphsTexture.clear(); + textures.clear(); fbo = 0; - size = QSize(); delete blitProgram; blitProgram = 0; + + currentTexture = addTexture(); } void freeResource(QOpenGLContext *ctx) { - glDeleteTextures(1, &texture); + glyphsTexture.clear(); + for (int i = 0; i < textures.count(); ++i) + glDeleteTextures(1, &textures[i].texture); + textures.clear(); ctx->functions()->glDeleteFramebuffers(1, &fbo); delete blitProgram; blitProgram = 0; + + currentTexture = addTexture(); } void createBlitProgram() @@ -155,6 +180,10 @@ private: } }; + void createTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height); + void resizeTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height); + bool textureIsFull (const DistanceFieldTextureData::TextureInfo *tex) const { return tex->currY >= maxTextureSize(); } + DistanceFieldTextureData *textureData(QOpenGLContext *c); DistanceFieldTextureData *m_textureData; static QHash m_textures_data; -- cgit v1.2.3 From 31467e8649979d06ea2f676768016e6a147eadb9 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 6 Mar 2012 18:03:33 +1000 Subject: Allow threaded compilation in an async Loader Enables threaded compilation for a Loader "source". Change-Id: I2d60a3ace07aab58f3b8f069e45a2864178c959f Reviewed-by: Chris Adams --- src/qml/qml/qqmlcomponent.cpp | 109 +++- src/qml/qml/qqmlcomponent.h | 6 + src/qml/qml/qqmlcomponent_p.h | 2 + src/qml/qml/qqmltypeloader.cpp | 4 +- src/qml/qml/qqmltypeloader_p.h | 2 +- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 27 +- src/quick/items/qquickloader.cpp | 9 +- .../qml/qqmlcomponent/data/TestComponent.2.qml | 591 ++++++++++++++++++++ .../auto/qml/qqmlcomponent/data/TestComponent.qml | 534 +++++++++++++++++++ tests/auto/qml/qqmlcomponent/qqmlcomponent.pro | 8 +- tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 101 ++++ tests/auto/qml/qqmlqt/data/TestComponent.2.qml | 592 +++++++++++++++++++++ tests/auto/qml/qqmlqt/data/TestComponent.3.qml | 89 ++++ tests/auto/qml/qqmlqt/data/TestComponent.qml | 534 +++++++++++++++++++ tests/auto/qml/qqmlqt/data/createComponent.2.qml | 27 + tests/auto/qml/qqmlqt/data/createComponent.qml | 13 + tests/auto/qml/qqmlqt/tst_qqmlqt.cpp | 13 + .../quick/qquickloader/data/TestComponent.2.qml | 592 +++++++++++++++++++++ .../auto/quick/qquickloader/data/TestComponent.qml | 89 ++++ .../auto/quick/qquickloader/data/simultaneous.qml | 22 + tests/auto/quick/qquickloader/tst_qquickloader.cpp | 53 +- 21 files changed, 3383 insertions(+), 34 deletions(-) create mode 100644 tests/auto/qml/qqmlcomponent/data/TestComponent.2.qml create mode 100644 tests/auto/qml/qqmlcomponent/data/TestComponent.qml create mode 100644 tests/auto/qml/qqmlqt/data/TestComponent.2.qml create mode 100644 tests/auto/qml/qqmlqt/data/TestComponent.3.qml create mode 100644 tests/auto/qml/qqmlqt/data/TestComponent.qml create mode 100644 tests/auto/qml/qqmlqt/data/createComponent.2.qml create mode 100644 tests/auto/quick/qquickloader/data/TestComponent.2.qml create mode 100644 tests/auto/quick/qquickloader/data/TestComponent.qml create mode 100644 tests/auto/quick/qquickloader/data/simultaneous.qml diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index a73fe7cd63..6cd5cf6cec 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -280,6 +280,16 @@ static inline QString buildTypeNameForDebug(const QMetaObject *metaObject) \value Error An error has occurred. Call errors() to retrieve a list of \{QQmlError}{errors}. */ +/*! + \enum QQmlComponent::CompilationMode + + Specifies whether the QQmlComponent should load the component immediately, or asynchonously. + + \value PreferSynchronous Prefer loading/compiling the component immediately, blocking the thread. + This is not always possible, e.g. remote URLs will always load asynchronously. + \value Asynchronous Load/compile the component in a background thread. +*/ + void QQmlComponentPrivate::typeDataReady(QQmlTypeData *) { Q_Q(QQmlComponent); @@ -288,8 +298,10 @@ void QQmlComponentPrivate::typeDataReady(QQmlTypeData *) fromTypeData(typeData); typeData = 0; + progress = 1.0; emit q->statusChanged(q->status()); + emit q->progressChanged(progress); } void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p) @@ -476,7 +488,24 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *paren { Q_D(QQmlComponent); d->engine = engine; - loadUrl(url); + d->loadUrl(url); +} + +/*! + Create a QQmlComponent from the given \a url and give it the + specified \a parent and \a engine. If \a mode is \l Asynchronous, + the component will be loaded and compiled asynchronously. + + Ensure that the URL provided is full and correct, in particular, use + \l QUrl::fromLocalFile() when loading a file from the local filesystem. + + \sa loadUrl() +*/QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, CompilationMode mode, QObject *parent) +: QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; + d->loadUrl(url, mode); } /*! @@ -491,7 +520,23 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName, { Q_D(QQmlComponent); d->engine = engine; - loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName))); + d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName))); +} + +/*! + Create a QQmlComponent from the given \a fileName and give it the specified + \a parent and \a engine. If \a mode is \l Asynchronous, + the component will be loaded and compiled asynchronously. + + \sa loadUrl() +*/ +QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName, + CompilationMode mode, QObject *parent) +: QObject(*(new QQmlComponentPrivate), parent) +{ + Q_D(QQmlComponent); + d->engine = engine; + d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)), mode); } /*! @@ -558,35 +603,63 @@ QQmlContext *QQmlComponent::creationContext() const void QQmlComponent::loadUrl(const QUrl &url) { Q_D(QQmlComponent); + d->loadUrl(url); +} - d->clear(); +/*! + Load the QQmlComponent from the provided \a url. + If \a mode is \l Asynchronous, the component will be loaded and compiled asynchronously. + + Ensure that the URL provided is full and correct, in particular, use + \l QUrl::fromLocalFile() when loading a file from the local filesystem. +*/ +void QQmlComponent::loadUrl(const QUrl &url, QQmlComponent::CompilationMode mode) +{ + Q_D(QQmlComponent); + d->loadUrl(url, mode); +} + +void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode) +{ + Q_Q(QQmlComponent); + clear(); - if ((url.isRelative() && !url.isEmpty()) - || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929 - d->url = d->engine->baseUrl().resolved(url); + if ((newUrl.isRelative() && !newUrl.isEmpty()) + || newUrl.scheme() == QLatin1String("file")) // Workaround QTBUG-11929 + url = engine->baseUrl().resolved(newUrl); else - d->url = url; + url = newUrl; - if (url.isEmpty()) { + if (newUrl.isEmpty()) { QQmlError error; - error.setDescription(tr("Invalid empty URL")); - d->state.errors << error; + error.setDescription(q->tr("Invalid empty URL")); + state.errors << error; return; } - QQmlTypeData *data = QQmlEnginePrivate::get(d->engine)->typeLoader.get(d->url); + if (progress != 0.0) { + progress = 0.0; + emit q->progressChanged(progress); + } + + QQmlDataLoader::Mode loaderMode = (mode == QQmlComponent::Asynchronous) + ? QQmlDataLoader::Asynchronous + : QQmlDataLoader::PreferSynchronous; + + QQmlTypeData *data = QQmlEnginePrivate::get(engine)->typeLoader.get(url, loaderMode); if (data->isCompleteOrError()) { - d->fromTypeData(data); - d->progress = 1.0; + fromTypeData(data); + progress = 1.0; } else { - d->typeData = data; - d->typeData->registerCallback(d); - d->progress = data->progress(); + typeData = data; + typeData->registerCallback(this); + progress = data->progress(); } - emit statusChanged(status()); - emit progressChanged(d->progress); + emit q->statusChanged(q->status()); + if (progress != 0.0) + emit q->progressChanged(progress); } /*! diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index 1265fb1c7d..9fc9388e41 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -73,10 +73,15 @@ class Q_QML_EXPORT QQmlComponent : public QObject Q_PROPERTY(QUrl url READ url CONSTANT) public: + Q_ENUMS(CompilationMode) + enum CompilationMode { PreferSynchronous, Asynchronous }; + QQmlComponent(QObject *parent = 0); QQmlComponent(QQmlEngine *, QObject *parent=0); QQmlComponent(QQmlEngine *, const QString &fileName, QObject *parent = 0); + QQmlComponent(QQmlEngine *, const QString &fileName, CompilationMode mode, QObject *parent = 0); QQmlComponent(QQmlEngine *, const QUrl &url, QObject *parent = 0); + QQmlComponent(QQmlEngine *, const QUrl &url, CompilationMode mode, QObject *parent = 0); virtual ~QQmlComponent(); Q_ENUMS(Status) @@ -108,6 +113,7 @@ public: public Q_SLOTS: void loadUrl(const QUrl &url); + void loadUrl(const QUrl &url, CompilationMode mode); void setData(const QByteArray &, const QUrl &baseUrl); Q_SIGNALS: diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index dda5bd0b71..9e220b5e95 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -86,6 +86,8 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public public: QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0) {} + void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous); + QObject *beginCreate(QQmlContextData *); void completeCreate(); void initializeObjectWithInitialProperties(v8::Handle qmlGlobal, v8::Handle valuemap, QObject *toCreate); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0082d55c48..36ba530338 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1171,7 +1171,7 @@ This enum defines the options that control the way type data is handled. /*! Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached. */ -QQmlTypeData *QQmlTypeLoader::get(const QUrl &url) +QQmlTypeData *QQmlTypeLoader::get(const QUrl &url, Mode mode) { Q_ASSERT(!url.isRelative() && (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || @@ -1184,7 +1184,7 @@ QQmlTypeData *QQmlTypeLoader::get(const QUrl &url) if (!typeData) { typeData = new QQmlTypeData(url, None, this); m_typeCache.insert(url, typeData); - QQmlDataLoader::load(typeData); + QQmlDataLoader::load(typeData, mode); } typeData->addref(); diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 0dd7adecac..c8c2756bd5 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -236,7 +236,7 @@ public: }; Q_DECLARE_FLAGS(Options, Option) - QQmlTypeData *get(const QUrl &url); + QQmlTypeData *get(const QUrl &url, Mode mode = PreferSynchronous); QQmlTypeData *get(const QByteArray &, const QUrl &url, Options = None); void clearCache(); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 11a233d093..b9f2b627da 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1120,7 +1120,7 @@ v8::Handle createQmlObject(const v8::Arguments &args) } /*! -\qmlmethod object Qt::createComponent(url) +\qmlmethod object Qt::createComponent(url, mode) Returns a \l Component object created using the QML file at the specified \a url, or \c null if an empty string was given. @@ -1129,6 +1129,12 @@ The returned component's \l Component::status property indicates whether the component was successfully created. If the status is \c Component.Error, see \l Component::errorString() for an error description. +If the optional \a mode parameter is set to \c Component.Asynchronous, the +component will be loaded in a background thread. The Component::status property +will be \c Component.Loading while it is loading. The status will change to +\c Component.Ready if the component loads successfully, or \c Component.Error +if loading fails. + Call \l {Component::createObject()}{Component.createObject()} on the returned component to create an object instance of the component. @@ -1143,8 +1149,9 @@ use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}. */ v8::Handle createComponent(const v8::Arguments &args) { - if (args.Length() != 1) - V8THROW_ERROR("Qt.createComponent(): Invalid arguments"); + const char *invalidArgs = "Qt.createComponent(): Invalid arguments"; + if (args.Length() < 1 || args.Length() > 2) + V8THROW_ERROR(invalidArgs); QV8Engine *v8engine = V8ENGINE(); QQmlEngine *engine = v8engine->engine(); @@ -1159,8 +1166,20 @@ v8::Handle createComponent(const v8::Arguments &args) if (arg.isEmpty()) return v8::Null(); + QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous; + if (args.Length() == 2) { + if (args[1]->IsInt32()) { + int mode = args[1]->Int32Value(); + if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous)) + V8THROW_ERROR(invalidArgs); + compileMode = QQmlComponent::CompilationMode(mode); + } else { + V8THROW_ERROR(invalidArgs); + } + } + QUrl url = context->resolvedUrl(QUrl(arg)); - QQmlComponent *c = new QQmlComponent(engine, url, engine); + QQmlComponent *c = new QQmlComponent(engine, url, compileMode, engine); QQmlComponentPrivate::get(c)->creationContext = effectiveContext; QQmlData::get(c, true)->setImplicitDestructible(); return v8engine->newQObject(c); diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 8877385b46..59cb37c15d 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -344,7 +344,8 @@ void QQuickLoader::loadFromSource() } if (isComponentComplete()) { - d->component = new QQmlComponent(qmlEngine(this), d->source, this); + QQmlComponent::CompilationMode mode = d->asynchronous ? QQmlComponent::Asynchronous : QQmlComponent::PreferSynchronous; + d->component = new QQmlComponent(qmlEngine(this), d->source, mode, this); d->load(); } } @@ -711,7 +712,8 @@ void QQuickLoader::componentComplete() QQuickItem::componentComplete(); if (active()) { if (d->loadingFromSource) { - d->component = new QQmlComponent(qmlEngine(this), d->source, this); + QQmlComponent::CompilationMode mode = d->asynchronous ? QQmlComponent::Asynchronous : QQmlComponent::PreferSynchronous; + d->component = new QQmlComponent(qmlEngine(this), d->source, mode, this); } d->load(); } @@ -752,6 +754,9 @@ qreal QQuickLoader::progress() const This property holds whether the component will be instantiated asynchronously. +When used in conjunction with the \l source property, loading and compilation +will also be performed in a background thread. + Loading asynchronously creates the objects declared by the component across multiple frames, and reduces the likelihood of glitches in animation. When loading asynchronously the status diff --git a/tests/auto/qml/qqmlcomponent/data/TestComponent.2.qml b/tests/auto/qml/qqmlcomponent/data/TestComponent.2.qml new file mode 100644 index 0000000000..fca43fe2dc --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/TestComponent.2.qml @@ -0,0 +1,591 @@ +import QtQuick 2.0 + +Item { + id: root + objectName: "root" + property int zero: 0 + + Item { + id: c1 + objectName: "c1" + property int one: zero + 1 + + Item { + id: c1c1 + objectName: "c1c1" + property bool two: c2c1c1.two + } + + Item { + id: c1c2 + objectName: "c1c2" + property string three: "three" + + Rectangle { + id: c1c2c3 + objectName: "c1c2c3" + property alias othercolor: c2c1.color + color: if (c2c1.color == Qt.rgba(0,0,1)) Qt.rgba(1,0,0); else Qt.rgba(0,1,0); + } + } + } + + Item { + id: c2 + objectName: "c2" + property string two: "two" + + Rectangle { + id: c2c1 + objectName: "c2c1" + property string three: "2" + c1c2.three + color: "blue" + + MouseArea { + id: c2c1c1 + objectName: "c2c1c1" + property bool two: false + onClicked: two = !two + } + + Item { + id: c2c1c2 + objectName: "c2c1c2" + property string three: "1" + parent.three + } + } + } + + Item { + id: c3 + objectName: "c3" + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + } + + property bool success: true + Component.onCompleted: { + // test state after initial bindings evaluation + if (zero != 0) success = false; + if (c1.one != 1) success = false; + if (c1c1.two != false) success = false; + if (c1c2.three != "three") success = false; + if (c1c2c3.color != Qt.rgba(1,0,0)) success = false; + if (c2.two != "two") success = false; + if (c2c1.three != "2three") success = false; + if (c2c1.color != Qt.rgba(0,0,1)) success = false; + if (c2c1c1.two != false) success = false; + if (c2c1c2.three != "12three") success = false; + if (c3.children.length != 500) success = false; + + // now retrigger bindings evaluation + root.zero = 5; + if (c1.one != 6) success = false; + c2c1c1.two = true; + if (c1c1.two != true) success = false; + c1c2.three = "3"; + if (c2c1.three != "23") success = false; + if (c2c1c2.three != "123") success = false; + c2c1.color = Qt.rgba(1,0,0); + if (c1c2c3.color != Qt.rgba(0,1,0)) success = false; + if (c1c2c3.othercolor != Qt.rgba(1,0,0)) success = false; + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/TestComponent.qml b/tests/auto/qml/qqmlcomponent/data/TestComponent.qml new file mode 100644 index 0000000000..64cec1cd06 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/TestComponent.qml @@ -0,0 +1,534 @@ +import QtQuick 2.0 + +Item { + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} +} diff --git a/tests/auto/qml/qqmlcomponent/qqmlcomponent.pro b/tests/auto/qml/qqmlcomponent/qqmlcomponent.pro index cf1c398ce5..6667513395 100644 --- a/tests/auto/qml/qqmlcomponent/qqmlcomponent.pro +++ b/tests/auto/qml/qqmlcomponent/qqmlcomponent.pro @@ -2,7 +2,11 @@ CONFIG += testcase TARGET = tst_qqmlcomponent macx:CONFIG -= app_bundle -SOURCES += tst_qqmlcomponent.cpp +INCLUDEPATH += ../../shared/ +SOURCES += tst_qqmlcomponent.cpp \ + ../../shared/testhttpserver.cpp + +HEADERS += ../../shared/testhttpserver.h include (../../shared/util.pri) @@ -10,4 +14,4 @@ TESTDATA = data/* CONFIG += parallel_test -QT += core-private gui-private qml-private network testlib +QT += core-private gui-private qml-private quick-private network testlib diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 603c091a03..10181aa9b8 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -45,8 +45,14 @@ #include #include #include +#include +#include +#include #include #include "../../shared/util.h" +#include "testhttpserver.h" + +#define SERVER_PORT 14450 class MyIC : public QObject, public QQmlIncubationController { @@ -59,6 +65,37 @@ protected: } }; +class ComponentWatcher : public QObject +{ + Q_OBJECT +public: + ComponentWatcher(QQmlComponent *comp) : loading(0), error(0), ready(0) { + connect(comp, SIGNAL(statusChanged(QQmlComponent::Status)), + this, SLOT(statusChanged(QQmlComponent::Status))); + } + + int loading; + int error; + int ready; + +public slots: + void statusChanged(QQmlComponent::Status status) { + switch (status) { + case QQmlComponent::Loading: + ++loading; + break; + case QQmlComponent::Error: + ++error; + break; + case QQmlComponent::Ready: + ++ready; + break; + default: + break; + } + } +}; + class tst_qqmlcomponent : public QQmlDataTest { Q_OBJECT @@ -72,6 +109,8 @@ private slots: void qmlCreateObjectWithProperties(); void qmlIncubateObject(); void qmlCreateParentReference(); + void async(); + void asyncHierarchy(); private: QQmlEngine engine; @@ -213,6 +252,68 @@ void tst_qqmlcomponent::qmlCreateParentReference() QCOMPARE(warnings.count(), 0); } +void tst_qqmlcomponent::async() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(dataDirectory()); + + QQmlComponent component(&engine); + ComponentWatcher watcher(&component); + component.loadUrl(QUrl("http://127.0.0.1:14450/TestComponent.qml"), QQmlComponent::Asynchronous); + QCOMPARE(watcher.loading, 1); + QTRY_VERIFY(component.isReady()); + QCOMPARE(watcher.ready, 1); + QCOMPARE(watcher.error, 0); + + QObject *object = component.create(); + QVERIFY(object != 0); + + delete object; +} + +void tst_qqmlcomponent::asyncHierarchy() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(dataDirectory()); + + // ensure that the item hierarchy is compiled correctly. + QQmlComponent component(&engine); + ComponentWatcher watcher(&component); + component.loadUrl(QUrl("http://127.0.0.1:14450/TestComponent.2.qml"), QQmlComponent::Asynchronous); + QCOMPARE(watcher.loading, 1); + QTRY_VERIFY(component.isReady()); + QCOMPARE(watcher.ready, 1); + QCOMPARE(watcher.error, 0); + + QObject *root = component.create(); + QVERIFY(root != 0); + + // ensure that the parent-child relationship hierarchy is correct + QQuickItem *c1 = root->findChild("c1", Qt::FindDirectChildrenOnly); + QVERIFY(c1); + QQuickItem *c1c1 = c1->findChild("c1c1", Qt::FindDirectChildrenOnly); + QVERIFY(c1c1); + QQuickItem *c1c2 = c1->findChild("c1c2", Qt::FindDirectChildrenOnly); + QVERIFY(c1c2); + QQuickRectangle *c1c2c3 = c1c2->findChild("c1c2c3", Qt::FindDirectChildrenOnly); + QVERIFY(c1c2c3); + QQuickItem *c2 = root->findChild("c2", Qt::FindDirectChildrenOnly); + QVERIFY(c2); + QQuickRectangle *c2c1 = c2->findChild("c2c1", Qt::FindDirectChildrenOnly); + QVERIFY(c2c1); + QQuickMouseArea *c2c1c1 = c2c1->findChild("c2c1c1", Qt::FindDirectChildrenOnly); + QVERIFY(c2c1c1); + QQuickItem *c2c1c2 = c2c1->findChild("c2c1c2", Qt::FindDirectChildrenOnly); + QVERIFY(c2c1c2); + + // ensure that values and bindings are assigned correctly + QVERIFY(root->property("success").toBool()); + + delete root; +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" diff --git a/tests/auto/qml/qqmlqt/data/TestComponent.2.qml b/tests/auto/qml/qqmlqt/data/TestComponent.2.qml new file mode 100644 index 0000000000..d6e99028b5 --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/TestComponent.2.qml @@ -0,0 +1,592 @@ +import QtQuick 2.0 + +Item { + id: root + objectName: "root" + property int zero: 0 + + Item { + id: c1 + objectName: "c1" + property int one: zero + 1 + + Item { + id: c1c1 + objectName: "c1c1" + property bool two: c2c1c1.two + } + + Item { + id: c1c2 + objectName: "c1c2" + property string three: "three" + + Rectangle { + id: c1c2c3 + objectName: "c1c2c3" + property alias othercolor: c2c1.color + color: if (c2c1.color == Qt.rgba(0,0,1)) Qt.rgba(1,0,0); else Qt.rgba(0,1,0); + } + } + } + + Item { + id: c2 + objectName: "c2" + property string two: "two" + + Rectangle { + id: c2c1 + objectName: "c2c1" + property string three: "2" + c1c2.three + color: "blue" + + MouseArea { + id: c2c1c1 + objectName: "c2c1c1" + property bool two: false + onClicked: two = !two + } + + Item { + id: c2c1c2 + objectName: "c2c1c2" + property string three: "1" + parent.three + } + } + } + + Item { + id: c3 + objectName: "c3" + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + } + + property alias c1one: c1.one + property bool success: true + Component.onCompleted: { + // test state after initial bindings evaluation + if (zero != 0) success = false; + if (c1.one != 1) success = false; + if (c1c1.two != false) success = false; + if (c1c2.three != "three") success = false; + if (c1c2c3.color != Qt.rgba(1,0,0)) success = false; + if (c2.two != "two") success = false; + if (c2c1.three != "2three") success = false; + if (c2c1.color != Qt.rgba(0,0,1)) success = false; + if (c2c1c1.two != false) success = false; + if (c2c1c2.three != "12three") success = false; + if (c3.children.length != 500) success = false; + + // now retrigger bindings evaluation + root.zero = 5; + if (c1.one != 6) success = false; + c2c1c1.two = true; + if (c1c1.two != true) success = false; + c1c2.three = "3"; + if (c2c1.three != "23") success = false; + if (c2c1c2.three != "123") success = false; + c2c1.color = Qt.rgba(1,0,0); + if (c1c2c3.color != Qt.rgba(0,1,0)) success = false; + if (c1c2c3.othercolor != Qt.rgba(1,0,0)) success = false; + } +} diff --git a/tests/auto/qml/qqmlqt/data/TestComponent.3.qml b/tests/auto/qml/qqmlqt/data/TestComponent.3.qml new file mode 100644 index 0000000000..81ea07cb88 --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/TestComponent.3.qml @@ -0,0 +1,89 @@ +import QtQuick 2.0 + +Item { + id: root + objectName: "root" + property int zero: 0 + property int one: 1 + + Item { + id: c1 + objectName: "c1" + property int one: zero + parent.one + + Item { + id: c1c1 + objectName: "c1c1" + property bool two: c2c1c1.two + } + + Item { + id: c1c2 + objectName: "c1c2" + property string three: "three" + + Rectangle { + id: c1c2c3 + objectName: "c1c2c3" + property alias othercolor: c2c1.color + color: if (c2c1.color == Qt.rgba(0,0,1)) Qt.rgba(1,0,0); else Qt.rgba(0,1,0); + } + } + } + + Item { + id: c2 + objectName: "c2" + property string two: "two" + + Rectangle { + id: c2c1 + objectName: "c2c1" + property string three: "2" + c1c2.three + color: "blue" + + MouseArea { + id: c2c1c1 + objectName: "c2c1c1" + property bool two: false + onClicked: two = !two + } + + Item { + id: c2c1c2 + objectName: "c2c1c2" + property string three: "1" + parent.three + } + } + } + + property alias c1one: c1.one + property bool success: true + Component.onCompleted: { + // test state after initial bindings evaluation + if (zero != 0) success = false; + if (c1.one != 1) success = false; + if (c1c1.two != false) success = false; + if (c1c2.three != "three") success = false; + if (c1c2c3.color != Qt.rgba(1,0,0)) success = false; + if (c2.two != "two") success = false; + if (c2c1.three != "2three") success = false; + if (c2c1.color != Qt.rgba(0,0,1)) success = false; + if (c2c1c1.two != false) success = false; + if (c2c1c2.three != "12three") success = false; + + // now retrigger bindings evaluation + root.zero = 5; + if (c1.one != 6) success = false; + root.one = 50; + if (c1.one != 55) success = false; + c2c1c1.two = true; + if (c1c1.two != true) success = false; + c1c2.three = "3"; + if (c2c1.three != "23") success = false; + if (c2c1c2.three != "123") success = false; + c2c1.color = Qt.rgba(1,0,0); + if (c1c2c3.color != Qt.rgba(0,1,0)) success = false; + if (c1c2c3.othercolor != Qt.rgba(1,0,0)) success = false; + } +} diff --git a/tests/auto/qml/qqmlqt/data/TestComponent.qml b/tests/auto/qml/qqmlqt/data/TestComponent.qml new file mode 100644 index 0000000000..64cec1cd06 --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/TestComponent.qml @@ -0,0 +1,534 @@ +import QtQuick 2.0 + +Item { + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} +} diff --git a/tests/auto/qml/qqmlqt/data/createComponent.2.qml b/tests/auto/qml/qqmlqt/data/createComponent.2.qml new file mode 100644 index 0000000000..36e2b23c9f --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/createComponent.2.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 + +Item { + property bool success: false + property var syncComponent + property var asyncComponent + + function asyncStatusChanged() { + if (asyncComponent.status == Component.Ready && syncComponent.status == Component.Ready) { + success = true; + var ao = asyncComponent.createObject(); + var so = syncComponent.createObject(); + if (ao.c1one != 6) success = false; + if (so.c1one != 55) success = false; + ao.destroy(); + so.destroy(); + } + } + + Component.onCompleted: { + asyncComponent = Qt.createComponent("TestComponent.2.qml", Component.Asynchronous); + if (asyncComponent.status != Component.Loading) + return; + asyncComponent.statusChanged.connect(asyncStatusChanged); + syncComponent = Qt.createComponent("TestComponent.3.qml", Component.PreferSynchronous); + } +} diff --git a/tests/auto/qml/qqmlqt/data/createComponent.qml b/tests/auto/qml/qqmlqt/data/createComponent.qml index 3ebc9f14f8..01b6490419 100644 --- a/tests/auto/qml/qqmlqt/data/createComponent.qml +++ b/tests/auto/qml/qqmlqt/data/createComponent.qml @@ -9,6 +9,14 @@ QtObject { property QtObject incorectArgCount1: Qt.createComponent() property QtObject incorectArgCount2: Qt.createComponent("main.qml", 10) + property bool asyncResult: false + property var asyncComponent + + function asyncStatusChanged() { + if (asyncComponent.status == Component.Ready) + asyncResult = true; + } + Component.onCompleted: { emptyArg = (Qt.createComponent("") == null); var r = Qt.createComponent("createComponentData.qml"); @@ -16,5 +24,10 @@ QtObject { var a = Qt.createComponent("http://www.example.com/test.qml"); absoluteUrl = a.url; + + asyncComponent = Qt.createComponent("TestComponent.qml", Component.Asynchronous); + if (asyncComponent.status != Component.Loading) + return; + asyncComponent.statusChanged.connect(asyncStatusChanged); } } diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index a679188cb7..d3dc3e7343 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -395,6 +395,7 @@ void tst_qqmlqt::md5() void tst_qqmlqt::createComponent() { + { QQmlComponent component(&engine, testFileUrl("createComponent.qml")); QString warning1 = component.url().toString() + ":9: Error: Qt.createComponent(): Invalid arguments"; @@ -408,7 +409,19 @@ void tst_qqmlqt::createComponent() QCOMPARE(object->property("absoluteUrl").toString(), QString("http://www.example.com/test.qml")); QCOMPARE(object->property("relativeUrl").toString(), testFileUrl("createComponentData.qml").toString()); + QTRY_VERIFY(object->property("asyncResult").toBool()); + delete object; + } + + // simultaneous sync and async compilation + { + QQmlComponent component(&engine, testFileUrl("createComponent.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QTRY_VERIFY(object->property("success").toBool()); + delete object; + } } void tst_qqmlqt::createComponent_pragmaLibrary() diff --git a/tests/auto/quick/qquickloader/data/TestComponent.2.qml b/tests/auto/quick/qquickloader/data/TestComponent.2.qml new file mode 100644 index 0000000000..d6e99028b5 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/TestComponent.2.qml @@ -0,0 +1,592 @@ +import QtQuick 2.0 + +Item { + id: root + objectName: "root" + property int zero: 0 + + Item { + id: c1 + objectName: "c1" + property int one: zero + 1 + + Item { + id: c1c1 + objectName: "c1c1" + property bool two: c2c1c1.two + } + + Item { + id: c1c2 + objectName: "c1c2" + property string three: "three" + + Rectangle { + id: c1c2c3 + objectName: "c1c2c3" + property alias othercolor: c2c1.color + color: if (c2c1.color == Qt.rgba(0,0,1)) Qt.rgba(1,0,0); else Qt.rgba(0,1,0); + } + } + } + + Item { + id: c2 + objectName: "c2" + property string two: "two" + + Rectangle { + id: c2c1 + objectName: "c2c1" + property string three: "2" + c1c2.three + color: "blue" + + MouseArea { + id: c2c1c1 + objectName: "c2c1c1" + property bool two: false + onClicked: two = !two + } + + Item { + id: c2c1c2 + objectName: "c2c1c2" + property string three: "1" + parent.three + } + } + } + + Item { + id: c3 + objectName: "c3" + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + Item {} + } + + property alias c1one: c1.one + property bool success: true + Component.onCompleted: { + // test state after initial bindings evaluation + if (zero != 0) success = false; + if (c1.one != 1) success = false; + if (c1c1.two != false) success = false; + if (c1c2.three != "three") success = false; + if (c1c2c3.color != Qt.rgba(1,0,0)) success = false; + if (c2.two != "two") success = false; + if (c2c1.three != "2three") success = false; + if (c2c1.color != Qt.rgba(0,0,1)) success = false; + if (c2c1c1.two != false) success = false; + if (c2c1c2.three != "12three") success = false; + if (c3.children.length != 500) success = false; + + // now retrigger bindings evaluation + root.zero = 5; + if (c1.one != 6) success = false; + c2c1c1.two = true; + if (c1c1.two != true) success = false; + c1c2.three = "3"; + if (c2c1.three != "23") success = false; + if (c2c1c2.three != "123") success = false; + c2c1.color = Qt.rgba(1,0,0); + if (c1c2c3.color != Qt.rgba(0,1,0)) success = false; + if (c1c2c3.othercolor != Qt.rgba(1,0,0)) success = false; + } +} diff --git a/tests/auto/quick/qquickloader/data/TestComponent.qml b/tests/auto/quick/qquickloader/data/TestComponent.qml new file mode 100644 index 0000000000..81ea07cb88 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/TestComponent.qml @@ -0,0 +1,89 @@ +import QtQuick 2.0 + +Item { + id: root + objectName: "root" + property int zero: 0 + property int one: 1 + + Item { + id: c1 + objectName: "c1" + property int one: zero + parent.one + + Item { + id: c1c1 + objectName: "c1c1" + property bool two: c2c1c1.two + } + + Item { + id: c1c2 + objectName: "c1c2" + property string three: "three" + + Rectangle { + id: c1c2c3 + objectName: "c1c2c3" + property alias othercolor: c2c1.color + color: if (c2c1.color == Qt.rgba(0,0,1)) Qt.rgba(1,0,0); else Qt.rgba(0,1,0); + } + } + } + + Item { + id: c2 + objectName: "c2" + property string two: "two" + + Rectangle { + id: c2c1 + objectName: "c2c1" + property string three: "2" + c1c2.three + color: "blue" + + MouseArea { + id: c2c1c1 + objectName: "c2c1c1" + property bool two: false + onClicked: two = !two + } + + Item { + id: c2c1c2 + objectName: "c2c1c2" + property string three: "1" + parent.three + } + } + } + + property alias c1one: c1.one + property bool success: true + Component.onCompleted: { + // test state after initial bindings evaluation + if (zero != 0) success = false; + if (c1.one != 1) success = false; + if (c1c1.two != false) success = false; + if (c1c2.three != "three") success = false; + if (c1c2c3.color != Qt.rgba(1,0,0)) success = false; + if (c2.two != "two") success = false; + if (c2c1.three != "2three") success = false; + if (c2c1.color != Qt.rgba(0,0,1)) success = false; + if (c2c1c1.two != false) success = false; + if (c2c1c2.three != "12three") success = false; + + // now retrigger bindings evaluation + root.zero = 5; + if (c1.one != 6) success = false; + root.one = 50; + if (c1.one != 55) success = false; + c2c1c1.two = true; + if (c1c1.two != true) success = false; + c1c2.three = "3"; + if (c2c1.three != "23") success = false; + if (c2c1c2.three != "123") success = false; + c2c1.color = Qt.rgba(1,0,0); + if (c1c2c3.color != Qt.rgba(0,1,0)) success = false; + if (c1c2c3.othercolor != Qt.rgba(1,0,0)) success = false; + } +} diff --git a/tests/auto/quick/qquickloader/data/simultaneous.qml b/tests/auto/quick/qquickloader/data/simultaneous.qml new file mode 100644 index 0000000000..cab6498863 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/simultaneous.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +Rectangle { + width: 400; height: 400 + + function loadComponents() { + asyncLoader.source = "TestComponent.2.qml" + syncLoader.source = "TestComponent.qml" + } + + Loader { + id: asyncLoader + objectName: "asyncLoader" + asynchronous: true + } + + Loader { + id: syncLoader + objectName: "syncLoader" + asynchronous: false + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 77d0c29220..b388243a1d 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -56,13 +56,21 @@ class PeriodicIncubationController : public QObject, { public: PeriodicIncubationController() { + incubated = false; startTimer(16); } + bool incubated; + protected: virtual void timerEvent(QTimerEvent *) { incubateFor(15); } + + virtual void incubatingObjectCountChanged(int count) { + if (count) + incubated = true; + } }; class tst_QQuickLoader : public QQmlDataTest @@ -102,6 +110,7 @@ private slots: void asynchronous_data(); void asynchronous(); void asynchronous_clear(); + void simultaneousSyncAsync(); void parented(); void sizeBound(); @@ -481,7 +490,7 @@ void tst_QQuickLoader::failNetworkRequest() QTRY_VERIFY(loader->status() == QQuickLoader::Error); QVERIFY(loader->item() == 0); - QCOMPARE(loader->progress(), 0.0); + QCOMPARE(loader->progress(), 1.0); QCOMPARE(loader->property("did_load").toInt(), 123); QCOMPARE(static_cast(loader)->childItems().count(), 0); @@ -856,7 +865,7 @@ void tst_QQuickLoader::asynchronous_data() QTest::newRow("Valid component") << testFileUrl("BigComponent.qml") << QStringList(); - QTest::newRow("Non-existant component") << testFileUrl("IDoNotExist.qml") + QTest::newRow("Non-existent component") << testFileUrl("IDoNotExist.qml") << (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": File not found")); QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml") @@ -870,6 +879,8 @@ void tst_QQuickLoader::asynchronous() if (!engine.incubationController()) engine.setIncubationController(new PeriodicIncubationController); + PeriodicIncubationController *controller = static_cast(engine.incubationController()); + controller->incubated = false; QQmlComponent component(&engine, testFileUrl("asynchronous.qml")); QQuickItem *root = qobject_cast(component.create()); QVERIFY(root); @@ -881,19 +892,20 @@ void tst_QQuickLoader::asynchronous() QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData()); QVERIFY(!loader->item()); + QCOMPARE(loader->progress(), 0.0); root->setProperty("comp", qmlFile.toString()); QMetaObject::invokeMethod(root, "loadComponent"); QVERIFY(!loader->item()); if (expectedWarnings.isEmpty()) { QCOMPARE(loader->status(), QQuickLoader::Loading); - QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1); - + QVERIFY(!controller->incubated); // asynchronous compilation means not immediately compiled/incubating. + QTRY_VERIFY(controller->incubated); // but should start incubating once compilation is complete. QTRY_VERIFY(loader->item()); QCOMPARE(loader->progress(), 1.0); QCOMPARE(loader->status(), QQuickLoader::Ready); } else { - QCOMPARE(loader->progress(), 1.0); + QTRY_COMPARE(loader->progress(), 1.0); QTRY_COMPARE(loader->status(), QQuickLoader::Error); } @@ -943,6 +955,37 @@ void tst_QQuickLoader::asynchronous_clear() QCOMPARE(static_cast(loader)->childItems().count(), 1); } +void tst_QQuickLoader::simultaneousSyncAsync() +{ + if (!engine.incubationController()) + engine.setIncubationController(new PeriodicIncubationController); + PeriodicIncubationController *controller = static_cast(engine.incubationController()); + controller->incubated = false; + QQmlComponent component(&engine, testFileUrl("simultaneous.qml")); + QQuickItem *root = qobject_cast(component.create()); + QVERIFY(root); + + QQuickLoader *asyncLoader = root->findChild("asyncLoader"); + QQuickLoader *syncLoader = root->findChild("syncLoader"); + QVERIFY(asyncLoader); + QVERIFY(syncLoader); + + QVERIFY(!asyncLoader->item()); + QVERIFY(!syncLoader->item()); + QMetaObject::invokeMethod(root, "loadComponents"); + QVERIFY(!asyncLoader->item()); + QVERIFY(syncLoader->item()); + + QCOMPARE(asyncLoader->status(), QQuickLoader::Loading); + QVERIFY(!controller->incubated); // asynchronous compilation means not immediately compiled/incubating. + QTRY_VERIFY(controller->incubated); // but should start incubating once compilation is complete. + QTRY_VERIFY(asyncLoader->item()); + QCOMPARE(asyncLoader->progress(), 1.0); + QCOMPARE(asyncLoader->status(), QQuickLoader::Ready); + + delete root; +} + void tst_QQuickLoader::parented() { QQmlComponent component(&engine, testFileUrl("parented.qml")); -- cgit v1.2.3 From 5adfdaf9b33923f4cd2137c055aa549915b120d1 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 14 Mar 2012 17:09:06 +0200 Subject: Fix tst_qquickimageparticle test compilation with Visual Studio MSVC doesn't support setenv or unsetenv functions, so use qputenv instead. Change-Id: Ife4eb056e6c87d23774512c61b13a3ae3d8ac9ce Reviewed-by: Friedemann Kleint --- tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp index b953859d8d..cbc09fdb53 100644 --- a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp +++ b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp @@ -69,12 +69,13 @@ void tst_qquickimageparticle::initTestCase() { QQmlDataTest::initTestCase(); QUnifiedTimer::instance()->setConsistentTiming(true); - setenv("QML_PARTICLES_DEBUG","please",0);//QQuickImageParticle has several debug statements, with possible pointer dereferences + //QQuickImageParticle has several debug statements, with possible pointer dereferences + qputenv("QML_PARTICLES_DEBUG","please"); } tst_qquickimageparticle::~tst_qquickimageparticle() { - unsetenv("QML_PARTICLES_DEBUG"); + qputenv("QML_PARTICLES_DEBUG",""); } void tst_qquickimageparticle::test_basic() -- cgit v1.2.3 From 21e228afa711ea040170445c649f725bedc394fe Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 14 Mar 2012 16:42:58 +0200 Subject: Windows: Fix file URL issues in declarative autotests Fixed by using testFileUrl() shared utility function where appropriate instead of testFile() or various other ways file URLs were being incorrectly used. Task-number: QTBUG-24779 Change-Id: I48cbd297d419238f42ea45132344b7e5a487b6f1 Reviewed-by: Friedemann Kleint --- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 16 +++++------ .../qquickfontloader/tst_qquickfontloader.cpp | 2 +- .../quick/qquickgridview/tst_qquickgridview.cpp | 2 +- .../quick/qquickitemlayer/tst_qquickitemlayer.cpp | 32 +++++++++++----------- tests/auto/quick/qquickloader/tst_qquickloader.cpp | 2 +- .../qquickmultipointtoucharea.pro | 2 ++ .../tst_qquickmultipointtoucharea.cpp | 6 ++-- .../qquickpositioners/tst_qquickpositioners.cpp | 4 +-- tests/auto/quick/rendernode/tst_rendernode.cpp | 8 +++--- 9 files changed, 39 insertions(+), 35 deletions(-) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 3bbbc2c79c..79eaa3316f 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3112,7 +3112,7 @@ void tst_qqmlecmascript::moduleApi_data() QTest::newRow("qobject, writing + readonly constraints") << testFileUrl("moduleapi/qobjectModuleApiWriting.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\""))) + << (QStringList() << QString(testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toString() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\""))) << (QStringList() << "readOnlyProperty" << "writableProperty" << "writableFinalProperty") << (QVariantList() << 20 << 50 << 10) << (QStringList() << "firstProperty" << "secondProperty") @@ -3123,7 +3123,7 @@ void tst_qqmlecmascript::moduleApi_data() QTest::newRow("script, writing + readonly constraints") << testFileUrl("moduleapi/scriptModuleApiWriting.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\""))) + << (QStringList() << QString(testFileUrl("moduleapi/scriptModuleApiWriting.qml").toString() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\""))) << (QStringList() << "readBack" << "unchanged") << (QVariantList() << 13 << 42) << (QStringList() << "firstProperty" << "secondProperty") @@ -3232,35 +3232,35 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("parent scope shouldn't be inherited by import with imports") << testFileUrl("jsimportfail/failOne.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/failOne.qml").toString() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined"))) << (QStringList() << QLatin1String("importScriptFunctionValue")) << (QVariantList() << QVariant(QString())); QTest::newRow("javascript imports in an import should be private to the import scope") << testFileUrl("jsimportfail/failTwo.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: ImportOneJs is not defined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/failTwo.qml").toString() + QLatin1String(":6: ReferenceError: ImportOneJs is not defined"))) << (QStringList() << QLatin1String("importScriptFunctionValue")) << (QVariantList() << QVariant(QString())); QTest::newRow("module imports in an import should be private to the import scope") << testFileUrl("jsimportfail/failThree.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/failThree.qml").toString() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined"))) << (QStringList() << QLatin1String("importedModuleAttachedPropertyValue")) << (QVariantList() << QVariant(false)); QTest::newRow("typenames in an import should be private to the import scope") << testFileUrl("jsimportfail/failFour.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: JsQtTest is not defined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/failFour.qml").toString() + QLatin1String(":6: ReferenceError: JsQtTest is not defined"))) << (QStringList() << QLatin1String("importedModuleEnumValue")) << (QVariantList() << QVariant(0)); QTest::newRow("import with imports has it's own activation scope") << testFileUrl("jsimportfail/failFive.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Component is not defined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/importWithImports.js").toString() + QLatin1String(":8: ReferenceError: Component is not defined"))) << (QStringList() << QLatin1String("componentError")) << (QVariantList() << QVariant(0)); @@ -3274,7 +3274,7 @@ void tst_qqmlecmascript::importScripts_data() QTest::newRow("pragma library imports shouldn't inherit parent imports or scope") << testFileUrl("jsimportfail/testImportPragmaLibrary.qml") << QString() - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Component is not defined"))) + << (QStringList() << QString(testFileUrl("jsimportfail/importPragmaLibrary.js").toString() + QLatin1String(":6: ReferenceError: Component is not defined"))) << (QStringList() << QLatin1String("testValue")) << (QVariantList() << QVariant(0)); diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp index d8f368cf3e..f99c26803d 100644 --- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp +++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp @@ -116,7 +116,7 @@ void tst_qquickfontloader::namedFont() void tst_qquickfontloader::localFont() { - QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFile("tarzeau_ocr_a.ttf") + "\" }"; + QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("tarzeau_ocr_a.ttf").toString() + "\" }"; QQmlComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickFontLoader *fontObject = qobject_cast(component.create()); diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 928151d59e..a282d55ac8 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -5186,7 +5186,7 @@ void tst_QQuickGridView::asynchronous() QQmlIncubationController controller; canvas->engine()->setIncubationController(&controller); - canvas->setSource(testFile("asyncloader.qml")); + canvas->setSource(testFileUrl("asyncloader.qml")); QQuickItem *rootObject = qobject_cast(canvas->rootObject()); QVERIFY(rootObject); diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp index 44d0d6d09c..4847dd3d1c 100644 --- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp +++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp @@ -53,10 +53,10 @@ class tst_QQuickItemLayer: public QQmlDataTest public: tst_QQuickItemLayer(); - QImage runTest(const QString &url) + QImage runTest(const QString &fileName) { QQuickView view; - view.setSource(QUrl(url)); + view.setSource(testFileUrl(fileName)); view.show(); QTest::qWaitForWindowShown(&view); @@ -135,7 +135,7 @@ void tst_QQuickItemLayer::layerSmooth() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("Smooth.qml")); + QImage fb = runTest("Smooth.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0, 0xff)); @@ -154,7 +154,7 @@ void tst_QQuickItemLayer::layerEnabled() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("Enabled.qml")); + QImage fb = runTest("Enabled.qml"); // Verify the banding QCOMPARE(fb.pixel(0, 0), fb.pixel(0, 1)); // Verify the gradient @@ -170,7 +170,7 @@ void tst_QQuickItemLayer::layerMipmap() { if (m_isMesaSoftwareRasterizer) QSKIP("Mipmapping does not work with the Mesa Software Rasterizer."); - QImage fb = runTest(testFile("Mipmap.qml")); + QImage fb = runTest("Mipmap.qml"); QVERIFY(fb.pixel(0, 0) != 0xff000000); QVERIFY(fb.pixel(0, 0) != 0xffffffff); } @@ -184,7 +184,7 @@ void tst_QQuickItemLayer::layerEffect() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("Effect.qml")); + QImage fb = runTest("Effect.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0)); } @@ -199,7 +199,7 @@ void tst_QQuickItemLayer::layerSourceRect() if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("SourceRect.qml")); + QImage fb = runTest("SourceRect.qml"); // Check that the edges are converted to blue QCOMPARE(fb.pixel(0, 0), qRgb(0, 0, 0xff)); @@ -219,7 +219,7 @@ void tst_QQuickItemLayer::layerIsTextureProvider() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("TextureProvider.qml")); + QImage fb = runTest("TextureProvider.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0)); } @@ -257,7 +257,7 @@ void tst_QQuickItemLayer::layerVisibility() QFETCH(qreal, opacity); QQuickView view; - view.setSource(testFile("Visible.qml")); + view.setSource(testFileUrl("Visible.qml")); QQuickItem *child = view.rootItem()->childItems().at(0); child->setProperty("layerVisible", visible); @@ -303,7 +303,7 @@ void tst_QQuickItemLayer::layerZOrder() QFETCH(bool, effect); QQuickView view; - view.setSource(testFile("ZOrder.qml")); + view.setSource(testFileUrl("ZOrder.qml")); QQuickItem *child = view.rootItem()->childItems().at(0); child->setProperty("layerEffect", effect); @@ -338,7 +338,7 @@ void tst_QQuickItemLayer::changeZOrder() QFETCH(bool, effect); QQuickView view; - view.setSource(testFile("ZOrderChange.qml")); + view.setSource(testFileUrl("ZOrderChange.qml")); QQuickItem *child = view.rootItem()->childItems().at(0); child->setProperty("layerEnabled", layered); @@ -388,20 +388,20 @@ void tst_QQuickItemLayer::changeZOrder() void tst_QQuickItemLayer::toggleLayerAndEffect() { // This test passes if it doesn't crash. - runTest(testFile("ToggleLayerAndEffect.qml")); + runTest("ToggleLayerAndEffect.qml"); } void tst_QQuickItemLayer::disableLayer() { // This test passes if it doesn't crash. - runTest(testFile("DisableLayer.qml")); + runTest("DisableLayer.qml"); } void tst_QQuickItemLayer::changeSamplerName() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("SamplerNameChange.qml")); + QImage fb = runTest("SamplerNameChange.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0, 0, 0xff)); } @@ -409,7 +409,7 @@ void tst_QQuickItemLayer::itemEffect() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); - QImage fb = runTest(testFile("ItemEffect.qml")); + QImage fb = runTest("ItemEffect.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(199, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(0, 199), qRgb(0, 0, 0xff)); @@ -418,7 +418,7 @@ void tst_QQuickItemLayer::itemEffect() void tst_QQuickItemLayer::rectangleEffect() { - QImage fb = runTest(testFile("RectangleEffect.qml")); + QImage fb = runTest("RectangleEffect.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0, 0xff, 0)); QCOMPARE(fb.pixel(199, 0), qRgb(0, 0xff, 0)); QCOMPARE(fb.pixel(0, 199), qRgb(0, 0xff, 0)); diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index b388243a1d..bdf47fa9e9 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -653,7 +653,7 @@ void tst_QQuickLoader::initialPropertyValues_data() << (QVariantList() << 2 << 0); QTest::newRow("set source with initial property values specified, active = false") << testFileUrl("initialPropertyValues.3.qml") - << (QStringList() << QString(QLatin1String("file://") + testFileUrl("initialPropertyValues.3.qml").toLocalFile() + QLatin1String(":16: TypeError: Cannot read property 'canary' of null"))) + << (QStringList() << QString(testFileUrl("initialPropertyValues.3.qml").toString() + QLatin1String(":16: TypeError: Cannot read property 'canary' of null"))) << (QStringList()) << (QVariantList()); diff --git a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro index 8181eb8c5f..6816566c25 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro +++ b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro @@ -6,4 +6,6 @@ SOURCES += tst_qquickmultipointtoucharea.cpp TESTDATA = data/* +include(../../shared/util.pri) + QT += core-private gui-private qml-private quick-private testlib diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index 507612f8ce..1e0cd4eead 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -44,14 +44,16 @@ #include #include #include +#include "../../shared/util.h" -class tst_QQuickMultiPointTouchArea: public QObject +class tst_QQuickMultiPointTouchArea : public QQmlDataTest { Q_OBJECT public: tst_QQuickMultiPointTouchArea() : device(0) { } private slots: void initTestCase() { + QQmlDataTest::initTestCase(); if (!device) { device = new QTouchDevice; device->setType(QTouchDevice::TouchScreen); @@ -714,7 +716,7 @@ void tst_QQuickMultiPointTouchArea::invisible() QQuickView *tst_QQuickMultiPointTouchArea::createAndShowView(const QString &file) { QQuickView *canvas = new QQuickView(0); - canvas->setSource(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + QLatin1String("/data/") + file)); + canvas->setSource(testFileUrl(file)); canvas->show(); canvas->requestActivateWindow(); QTest::qWaitForWindowShown(canvas); diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp index 8f517a4fe3..ab24fbe995 100644 --- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp +++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp @@ -532,7 +532,7 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName) ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom); ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); - canvas->setSource(testFile("transitions.qml")); + canvas->setSource(testFileUrl("transitions.qml")); canvas->show(); qApp->processEvents(); @@ -641,7 +641,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName) ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia); ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom); ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia); - canvas->setSource(testFile("transitions.qml")); + canvas->setSource(testFileUrl("transitions.qml")); canvas->show(); qApp->processEvents(); diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp index b456a5980e..f3832b436f 100644 --- a/tests/auto/quick/rendernode/tst_rendernode.cpp +++ b/tests/auto/quick/rendernode/tst_rendernode.cpp @@ -54,10 +54,10 @@ class tst_rendernode: public QQmlDataTest public: tst_rendernode(); - QImage runTest(const QString &url) + QImage runTest(const QString &fileName) { QQuickView view; - view.setSource(QUrl(url)); + view.setSource(testFileUrl(fileName)); view.show(); QTest::qWaitForWindowShown(&view); @@ -194,7 +194,7 @@ static void fuzzyCompareColor(QRgb x, QRgb y) void tst_rendernode::renderOrder() { - QImage fb = runTest(testFile("RenderOrder.qml")); + QImage fb = runTest("RenderOrder.qml"); int x1 = fb.width() / 8; int x2 = fb.width() * 3 / 8; int x3 = fb.width() * 5 / 8; @@ -216,7 +216,7 @@ void tst_rendernode::renderOrder() void tst_rendernode::messUpState() { - QImage fb = runTest(testFile("MessUpState.qml")); + QImage fb = runTest("MessUpState.qml"); int x1 = 0; int x2 = fb.width() / 2; int x3 = fb.width() - 1; -- cgit v1.2.3 From 49b451dae44d801524288d16d8f45a3ef583275e Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Tue, 13 Mar 2012 21:34:05 +0100 Subject: Small LSB hacks Enable building QtDeclarative with the LSB compiler Change-Id: I3a81247670f47db3d861910150a722bc8ac7691a Reviewed-by: Roberto Raggi --- src/qml/qml/qqmltypeloader.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 36ba530338..781915e23e 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -63,6 +63,19 @@ #include #endif +#if defined (QT_LINUXBASE) +// LSB doesn't declare NAME_MAX. Use SYMLINK_MAX instead, which seems to +// always be identical to NAME_MAX +#ifndef NAME_MAX +# define NAME_MAX _POSIX_SYMLINK_MAX +#endif + +// LSB has a broken version of offsetof that can't be used at compile time +// https://lsbbugs.linuxfoundation.org/show_bug.cgi?id=3462 +#undef offsetof +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) +#endif + // #define DATABLOB_DEBUG #ifdef DATABLOB_DEBUG -- cgit v1.2.3 From 20ffaaf2977255147ad8a45762d5efb6b5635829 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 14 Mar 2012 11:35:13 +1000 Subject: Fix bug in v4 strict equality. Change-Id: I184065e0b7c8c6536f2081b9bf03e98992a4c9fe Reviewed-by: Roberto Raggi --- src/qml/qml/v4/qv4bindings.cpp | 45 +++++++++++++++++++++++++++++++ src/qml/qml/v4/qv4compiler.cpp | 16 ++++++++++- src/qml/qml/v4/qv4instruction.cpp | 15 +++++++++++ src/qml/qml/v4/qv4instruction_p.h | 11 ++++++++ src/qml/qml/v4/qv4irbuilder.cpp | 28 ++++++++++--------- src/qml/qml/v4/qv4program_p.h | 1 + tests/auto/qml/v4/data/equals.qml | 48 +++++++++++++++++++++++++++++++++ tests/auto/qml/v4/data/strictEquals.qml | 48 +++++++++++++++++++++++++++++++++ tests/auto/qml/v4/tst_v4.cpp | 2 ++ 9 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 tests/auto/qml/v4/data/equals.qml create mode 100644 tests/auto/qml/v4/data/strictEquals.qml diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index 89e831ca3f..5d367f2ae6 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -66,6 +66,7 @@ struct Register { typedef QQmlRegisterType Type; void setUndefined() { dataType = UndefinedType; } + void setNull() { dataType = NullType; } void setNaN() { setqreal(qSNaN()); } bool isUndefined() const { return dataType == UndefinedType; } @@ -1239,6 +1240,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(MathPIReal, unaryop) + QML_V4_BEGIN_INSTR(LoadNull, null_value) + registers[instr->null_value.reg].setNull(); + QML_V4_END_INSTR(LoadNull, null_value) + QML_V4_BEGIN_INSTR(LoadReal, real_value) registers[instr->real_value.reg].setqreal(instr->real_value.value); QML_V4_END_INSTR(LoadReal, real_value) @@ -1521,6 +1526,46 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, } QML_V4_END_INSTR(StrictNotEqualString, binaryop) + QML_V4_BEGIN_INSTR(EqualObject, binaryop) + { + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject(); + QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject(); + registers[instr->binaryop.output].setbool(leftobj == rightobj); + } + QML_V4_END_INSTR(EqualObject, binaryop) + + QML_V4_BEGIN_INSTR(NotEqualObject, binaryop) + { + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject(); + QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject(); + registers[instr->binaryop.output].setbool(leftobj != rightobj); + } + QML_V4_END_INSTR(NotEqualObject, binaryop) + + QML_V4_BEGIN_INSTR(StrictEqualObject, binaryop) + { + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject(); + QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject(); + registers[instr->binaryop.output].setbool(leftobj == rightobj); + } + QML_V4_END_INSTR(StrictEqualObject, binaryop) + + QML_V4_BEGIN_INSTR(StrictNotEqualObject, binaryop) + { + const Register &left = registers[instr->binaryop.left]; + const Register &right = registers[instr->binaryop.right]; + QObject *leftobj = (left.gettype() == NullType) ? 0 : left.getQObject(); + QObject *rightobj = (right.gettype() == NullType) ? 0 : right.getQObject(); + registers[instr->binaryop.output].setbool(leftobj != rightobj); + } + QML_V4_END_INSTR(StrictNotEqualObject, binaryop) + QML_V4_BEGIN_INSTR(MathMaxReal, binaryop) { const Register &left = registers[instr->binaryop.left]; diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index b22708d7db..09b0f3861b 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -234,6 +234,12 @@ void QV4CompilerPrivate::visitConst(IR::Const *e) gen(i); } break; + case IR::NullType: { + Instr::LoadNull i; + i.reg = currentReg; + gen(i); + } break; + default: if (qmlVerboseCompiler()) qWarning() << Q_FUNC_INFO << "unexpected type"; @@ -682,21 +688,29 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e) return V4Instr::LeReal; case IR::OpEqual: + if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) + return V4Instr::EqualObject; if (e->left->type == IR::StringType) return V4Instr::EqualString; return V4Instr::EqualReal; case IR::OpNotEqual: + if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) + return V4Instr::NotEqualObject; if (e->left->type == IR::StringType) return V4Instr::NotEqualString; return V4Instr::NotEqualReal; case IR::OpStrictEqual: + if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) + return V4Instr::StrictEqualObject; if (e->left->type == IR::StringType) return V4Instr::StrictEqualString; return V4Instr::StrictEqualReal; case IR::OpStrictNotEqual: + if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType) + return V4Instr::StrictNotEqualObject; if (e->left->type == IR::StringType) return V4Instr::StrictNotEqualString; return V4Instr::StrictNotEqualReal; @@ -774,7 +788,7 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) case IR::OpNotEqual: case IR::OpStrictEqual: case IR::OpStrictNotEqual: - if (e->left->type != IR::StringType) { + if (e->left->type >= IR::FirstNumberType) { convertToReal(e->left, left); convertToReal(e->right, right); } diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp index e26014765d..1ed8bd245e 100644 --- a/src/qml/qml/v4/qv4instruction.cpp +++ b/src/qml/qml/v4/qv4instruction.cpp @@ -213,6 +213,9 @@ void Bytecode::dump(const V4Instr *i, int address) const case V4Instr::MathPIReal: INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")"; break; + case V4Instr::LoadNull: + INSTR_DUMP << "\t" << "LoadNull" << "\t\t" << "Constant(null) -> Output_Reg(" << i->null_value.reg << ")"; + break; case V4Instr::LoadReal: INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")"; break; @@ -315,6 +318,18 @@ void Bytecode::dump(const V4Instr *i, int address) const case V4Instr::StrictNotEqualString: INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; break; + case V4Instr::EqualObject: + INSTR_DUMP << "\t" << "EqualObject" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::NotEqualObject: + INSTR_DUMP << "\t" << "NotEqualObject" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictEqualObject: + INSTR_DUMP << "\t" << "StrictEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; + case V4Instr::StrictNotEqualObject: + INSTR_DUMP << "\t" << "StrictNotEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; + break; case V4Instr::MathMaxReal: INSTR_DUMP << "\t" << "MathMaxReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")"; break; diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h index d33051840d..d6c790e46f 100644 --- a/src/qml/qml/v4/qv4instruction_p.h +++ b/src/qml/qml/v4/qv4instruction_p.h @@ -106,6 +106,7 @@ QT_BEGIN_NAMESPACE F(MathFloorReal, unaryop) \ F(MathCeilReal, unaryop) \ F(MathPIReal, unaryop) \ + F(LoadNull, null_value) \ F(LoadReal, real_value) \ F(LoadInt, int_value) \ F(LoadBool, bool_value) \ @@ -140,6 +141,10 @@ QT_BEGIN_NAMESPACE F(NotEqualString, binaryop) \ F(StrictEqualString, binaryop) \ F(StrictNotEqualString, binaryop) \ + F(EqualObject, binaryop) \ + F(NotEqualObject, binaryop) \ + F(StrictEqualObject, binaryop) \ + F(StrictNotEqualObject, binaryop) \ F(MathMaxReal, binaryop) \ F(MathMinReal, binaryop) \ F(NewString, construct) \ @@ -271,6 +276,11 @@ union V4Instr { qint8 reg; }; + struct instr_null_value { + QML_V4_INSTR_HEADER + qint8 reg; + }; + struct instr_real_value { QML_V4_INSTR_HEADER qint8 reg; @@ -358,6 +368,7 @@ union V4Instr { instr_fetch fetch; instr_copy copy; instr_construct construct; + instr_null_value null_value; instr_real_value real_value; instr_int_value int_value; instr_bool_value bool_value; diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 06178259f2..481b23eb4a 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -881,13 +881,15 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult implicitCvt(left, t); implicitCvt(right, t); } + } else if ((left.type() != IR::ObjectType && left.type() != IR::NullType) || + (right.type() != IR::ObjectType && right.type() != IR::NullType)) + return; - if (_expr.hint == ExprResult::cx) { - _expr.format = ExprResult::cx; - _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); - } else { - _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right); - } + if (_expr.hint == ExprResult::cx) { + _expr.format = ExprResult::cx; + _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); + } else { + _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right); } } @@ -999,9 +1001,6 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) implicitCvt(left, IR::RealType); implicitCvt(right, IR::RealType); binop(ast, left, right); - } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) { - implicitCvt(left, IR::BoolType); - implicitCvt(right, IR::BoolType); } else if (left.isValid() && right.isValid()) { binop(ast, left, right); } @@ -1013,16 +1012,21 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast) ExprResult right = expression(ast->right); if (left.type() == right.type()) { binop(ast, left, right); - } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) { + } else if (left.type() > IR::BoolType && right.type() > IR::BoolType) { // left and right have numeric type (int or real) binop(ast, left, right); + } else if ((left.type() == IR::ObjectType && right.type() == IR::NullType) || + (right.type() == IR::ObjectType && left.type() == IR::NullType)) { + // comparing a qobject with null + binop(ast, left, right); } else if (left.isValid() && right.isValid()) { + // left and right have different types const bool isEq = ast->op == QSOperator::StrictEqual; if (_expr.hint == ExprResult::cx) { _expr.format = ExprResult::cx; - _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse); + _block->JUMP(isEq ? _expr.iffalse : _expr.iftrue); } else { - _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0); + _expr.code = _block->CONST(IR::BoolType, isEq ? 0 : 1); } } } break; diff --git a/src/qml/qml/v4/qv4program_p.h b/src/qml/qml/v4/qv4program_p.h index d23cc6192f..60e7403786 100644 --- a/src/qml/qml/v4/qv4program_p.h +++ b/src/qml/qml/v4/qv4program_p.h @@ -85,6 +85,7 @@ struct QV4Program { enum QQmlRegisterType { UndefinedType, + NullType, QObjectStarType, QRealType, IntType, diff --git a/tests/auto/qml/v4/data/equals.qml b/tests/auto/qml/v4/data/equals.qml new file mode 100644 index 0000000000..c32603cc7e --- /dev/null +++ b/tests/auto/qml/v4/data/equals.qml @@ -0,0 +1,48 @@ +import QtQuick 2.0 + +QtObject { + property QtObject myprop1: null + property QtObject myprop2: QtObject {} + property real zero: 0 + property bool falseProp: false + + property bool test1: myprop1 == false + property bool test2: myprop1 == null + property bool test3: 5 == myprop1 + property bool test4: null == myprop1 + property bool test5: myprop1 != false + property bool test6: myprop1 != null + property bool test7: 5 != myprop1 + property bool test8: null != myprop1 + + property bool test9: myprop2 == false + property bool test10: myprop2 == null + property bool test11: 5 == myprop2 + property bool test12: null == myprop2 + property bool test13: myprop2 != false + property bool test14: myprop2 != null + property bool test15: 5 != myprop2 + property bool test16: null != myprop2 + + property bool test17: myprop1 == myprop1 + property bool test18: myprop1 != myprop1 + property bool test19: myprop1 == myprop2 + property bool test20: myprop1 != myprop2 + property bool test21: myprop2 == myprop2 + property bool test22: myprop2 != myprop2 + + property bool test23: myprop1 == "hello" + property bool test24: myprop1 != "hello" + property bool test25: myprop2 == "hello" + property bool test26: myprop2 != "hello" + + property bool test27: falseProp == zero + property bool test28: falseProp != zero + property bool test29: falseProp == 1 + property bool test30: falseProp != 1 + property bool test31: true == zero + property bool test32: true != zero + property bool test33: true == 1 + property bool test34: true != 1 +} + diff --git a/tests/auto/qml/v4/data/strictEquals.qml b/tests/auto/qml/v4/data/strictEquals.qml new file mode 100644 index 0000000000..3f4d0d8b3f --- /dev/null +++ b/tests/auto/qml/v4/data/strictEquals.qml @@ -0,0 +1,48 @@ +import QtQuick 2.0 + +QtObject { + property QtObject myprop1: null + property QtObject myprop2: QtObject {} + property real zero: 0 + property bool falseProp: false + + property bool test1: myprop1 === false + property bool test2: myprop1 === null + property bool test3: 5 === myprop1 + property bool test4: null === myprop1 + property bool test5: myprop1 !== false + property bool test6: myprop1 !== null + property bool test7: 5 !== myprop1 + property bool test8: null !== myprop1 + + property bool test9: myprop2 === false + property bool test10: myprop2 === null + property bool test11: 5 === myprop2 + property bool test12: null === myprop2 + property bool test13: myprop2 !== false + property bool test14: myprop2 !== null + property bool test15: 5 !== myprop2 + property bool test16: null !== myprop2 + + property bool test17: myprop1 === myprop1 + property bool test18: myprop1 !== myprop1 + property bool test19: myprop1 === myprop2 + property bool test20: myprop1 !== myprop2 + property bool test21: myprop2 === myprop2 + property bool test22: myprop2 !== myprop2 + + property bool test23: myprop1 === "hello" + property bool test24: myprop1 !== "hello" + property bool test25: myprop2 === "hello" + property bool test26: myprop2 !== "hello" + + property bool test27: falseProp === zero + property bool test28: falseProp !== zero + property bool test29: falseProp === 1 + property bool test30: falseProp !== 1 + property bool test31: true === zero + property bool test32: true !== zero + property bool test33: true === 1 + property bool test34: true !== 1 +} + diff --git a/tests/auto/qml/v4/tst_v4.cpp b/tests/auto/qml/v4/tst_v4.cpp index ed65cd2a82..1c89617157 100644 --- a/tests/auto/qml/v4/tst_v4.cpp +++ b/tests/auto/qml/v4/tst_v4.cpp @@ -124,6 +124,8 @@ void tst_v4::qtscript_data() { QTest::addColumn("file"); + QTest::newRow("equals") << "equals.qml"; + QTest::newRow("strict equals") << "strictEquals.qml"; QTest::newRow("qreal -> int rounding") << "qrealToIntRounding.qml"; QTest::newRow("exception on fetch") << "fetchException.qml"; QTest::newRow("logical or") << "logicalOr.qml"; -- cgit v1.2.3 From 6500e8c572261770185b9dc0e3764758cf651e2d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 19 Mar 2012 13:33:23 +1000 Subject: Fix grabbing to wait until the image has actually been grabbed. Change-Id: I3535c57b5d8dd99c8a6cf24ccb1b56af298fcfe6 Reviewed-by: Martin Jones --- src/quick/items/qquickwindowmanager.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp index 12c5dbd932..64eb2bf53b 100644 --- a/src/quick/items/qquickwindowmanager.cpp +++ b/src/quick/items/qquickwindowmanager.cpp @@ -107,11 +107,6 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_ lock. This variable is an integer to allow for recursive calls to lockInGui() without using a recursive mutex. See isPostingSyncEvent. - RenderThread::isPaintComplete: This variable is cleared when rendering starts and - set once rendering is complete. It is monitored in the paintEvent(), - resizeEvent() and grab() functions to force them to wait for rendering to - complete. - RenderThread::isPostingSyncEvent: This variable is set in the render thread just before the sync event is sent to the GUI thread. It is used to avoid deadlocks in the case where render thread waits while waiting for GUI to pick up the sync @@ -160,7 +155,6 @@ public: , allowMainThreadProcessingFlag(false) , isGuiLocked(0) , animationRunning(false) - , isPaintCompleted(false) , isPostingSyncEvent(false) , isRenderBlocked(false) , isExternalUpdatePending(false) @@ -248,7 +242,6 @@ private: int isGuiLocked; uint animationRunning: 1; - uint isPaintCompleted : 1; uint isPostingSyncEvent : 1; uint isRenderBlocked : 1; uint isExternalUpdatePending : 1; @@ -723,8 +716,6 @@ void QQuickRenderThreadSingleContextWindowManager::run() handleRemovedWindows(); - isPaintCompleted = true; - // Update sizes... for (QHash::const_iterator it = m_rendered_windows.constBegin(); it != m_rendered_windows.constEnd(); ++it) { @@ -1077,8 +1068,7 @@ QImage QQuickRenderThreadSingleContextWindowManager::grab(QQuickCanvas *canvas) exhaustSyncEvent(); canvasToGrab = canvas; - isPaintCompleted = false; - while (isRunning() && !isPaintCompleted) { + while (isRunning() && canvasToGrab) { if (isRenderBlocked) wake(); wait(); -- cgit v1.2.3 From 6cb590105f2830d60fdbc371651672745d809230 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 19 Mar 2012 17:27:38 +1000 Subject: Fix QQuickCanvas test failure. Switch to a QTRY_COMPARE to allow a little more time processing the event loop. Change-Id: I4f14feb5cbc7d11654f6c9089baff4ae67d894db Reviewed-by: Martin Jones --- tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp b/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp index 3a27d179c5..7250504e73 100644 --- a/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp +++ b/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp @@ -698,7 +698,7 @@ void tst_qquickcanvas::headless() canvas->show(); QTest::qWaitForWindowShown(canvas); - QCOMPARE(initialized.size(), 1); + QTRY_COMPARE(initialized.size(), 1); QVERIFY(canvas->openglContext() != 0); // Verify that the visual output is the same -- cgit v1.2.3 From cbe346a906f025af932b67c7c9672b109e218fa0 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 16 Mar 2012 14:48:58 +1000 Subject: Don't crash view while changing model. Set model to null before adjusting view position, as changing position can trigger a refill() if the view is animating at that instance. Change-Id: I4bc20766b1ab906799213b149c84a1bdb268c200 Reviewed-by: Bea Lam --- src/quick/items/qquickitemview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 501b206ef6..5089d230d7 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -257,8 +257,8 @@ void QQuickItemView::setModel(const QVariant &model) QQuickVisualModel *oldModel = d->model; d->clear(); - d->setPosition(d->contentStartOffset()); d->model = 0; + d->setPosition(d->contentStartOffset()); d->modelVariant = model; QObject *object = qvariant_cast(model); -- cgit v1.2.3 From f079f789c593996b0023afd6318d60d18ac66578 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 16 Mar 2012 17:01:11 +1000 Subject: Ensure section header/footer are cleaned up. If the model is cleared or replaced with an empty one, the section headers should be released. Change-Id: Ia2f070c312593743b2c5332a6c69facaf222ee6d Reviewed-by: Bea Lam --- src/quick/items/qquicklistview.cpp | 12 ++++++++---- tests/auto/quick/qquicklistview/tst_qquicklistview.cpp | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 2590d4691f..9d9e3ae186 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -524,7 +524,9 @@ void QQuickListViewPrivate::clear() sectionCache[i] = 0; } visiblePos = 0; + releaseSectionItem(currentSectionItem); currentSectionItem = 0; + releaseSectionItem(nextSectionItem); nextSectionItem = 0; lastVisibleSection = QString(); QQuickItemViewPrivate::clear(); @@ -933,6 +935,8 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString §ion) void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item) { + if (!item) + return; int i = 0; do { if (!sectionCache[i]) { @@ -970,7 +974,7 @@ void QQuickListViewPrivate::updateInlineSection(FxListItemSG *listItem) void QQuickListViewPrivate::updateStickySections() { - if (!sectionCriteria || visibleItems.isEmpty() + if (!sectionCriteria || (!sectionCriteria->labelPositioning() && !currentSectionItem && !nextSectionItem)) return; @@ -1006,7 +1010,7 @@ void QQuickListViewPrivate::updateStickySections() } // Current section header - if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart) { + if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.count()) { if (!currentSectionItem) { currentSectionItem = getSectionItem(currentSection); } else if (currentStickySection != currentSection) { @@ -1039,7 +1043,7 @@ void QQuickListViewPrivate::updateStickySections() } // Next section footer - if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd) { + if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.count()) { if (!nextSectionItem) { nextSectionItem = getSectionItem(nextSection); } else if (nextStickySection != nextSection) { @@ -1077,7 +1081,7 @@ void QQuickListViewPrivate::updateSections() QQuickItemViewPrivate::updateSections(); - if (sectionCriteria && !visibleItems.isEmpty()) { + if (sectionCriteria && !visibleItems.isEmpty() && isValid()) { QString prevSection; if (visibleIndex > 0) prevSection = sectionAt(visibleIndex-1); diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 14707cab1d..335fc3c6e2 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -2182,6 +2182,23 @@ void tst_QQuickListView::sectionsPositioning() QTRY_VERIFY(item = findVisibleChild(contentItem, "sect_aaa")); // inline label restored QCOMPARE(item->y(), 0.); + // if an empty model is set the header/footer should be cleaned up + canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart | QQuickViewSection::NextLabelAtEnd))); + QTRY_VERIFY(findVisibleChild(contentItem, "sect_aaa")); // section header + QTRY_VERIFY(findVisibleChild(contentItem, "sect_new")); // section footer + QmlListModel model1; + ctxt->setContextProperty("testModel", &model1); + QTRY_VERIFY(!findVisibleChild(contentItem, "sect_aaa")); // section header + QTRY_VERIFY(!findVisibleChild(contentItem, "sect_new")); // section footer + + // clear model - header/footer should be cleaned up + ctxt->setContextProperty("testModel", &model); + QTRY_VERIFY(findVisibleChild(contentItem, "sect_aaa")); // section header + QTRY_VERIFY(findVisibleChild(contentItem, "sect_new")); // section footer + model.clear(); + QTRY_VERIFY(!findVisibleChild(contentItem, "sect_aaa")); // section header + QTRY_VERIFY(!findVisibleChild(contentItem, "sect_new")); // section footer + delete canvas; } -- cgit v1.2.3 From 6deb3ceffa209d710570ffeb361e95c988e6e7cd Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 16 Mar 2012 18:45:39 +1000 Subject: Resetting a model can cause a crash in views with header/footer. Geometry listeners were called for deleted header/footer. Change-Id: I47854178232f8a4ab5e19a931901b49741fec388 Reviewed-by: Bea Lam --- src/quick/items/qquickgridview.cpp | 25 ++-- src/quick/items/qquickitemview.cpp | 11 +- src/quick/items/qquickitemview_p_p.h | 7 +- src/quick/items/qquicklistview.cpp | 25 ++-- .../quick/qquickgridview/data/headerfooter.qml | 31 +++++ .../quick/qquickgridview/tst_qquickgridview.cpp | 146 +++++++++++++++++++++ .../quick/qquicklistview/data/headerfooter.qml | 2 + .../quick/qquicklistview/tst_qquicklistview.cpp | 39 ++++++ 8 files changed, 261 insertions(+), 25 deletions(-) create mode 100644 tests/auto/quick/qquickgridview/data/headerfooter.qml diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index dd7a3faa6f..1fab4a8c99 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -66,13 +66,22 @@ QT_BEGIN_NAMESPACE class FxGridItemSG : public FxViewItem { public: - FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, own), view(v) { + FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) { attached = static_cast(qmlAttachedPropertiesObject(item)); if (attached) static_cast(attached)->setView(view); + if (trackGeometry) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } } - ~FxGridItemSG() {} + ~FxGridItemSG() { + if (trackGeom) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } + } qreal position() const { return rowPos(); @@ -423,7 +432,7 @@ FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item) { Q_Q(QQuickGridView); Q_UNUSED(modelIndex); - return new FxGridItemSG(item, q, false); + return new FxGridItemSG(item, q, false, false); } void QQuickGridViewPrivate::initializeViewItem(FxViewItem *item) @@ -685,7 +694,7 @@ void QQuickGridViewPrivate::createHighlight() if (currentItem) { QQuickItem *item = createHighlightItem(); if (item) { - FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true); + FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true, true); if (autoHighlight) resetHighlightPosition(); highlightXAnimator = new QSmoothedAnimation; @@ -760,11 +769,11 @@ void QQuickGridViewPrivate::updateFooter() Q_Q(QQuickGridView); bool created = false; if (!footer) { - QQuickItem *item = createComponentItem(footerComponent, true); + QQuickItem *item = createComponentItem(footerComponent); if (!item) return; item->setZ(1); - footer = new FxGridItemSG(item, q, true); + footer = new FxGridItemSG(item, q, true, true); created = true; } @@ -799,11 +808,11 @@ void QQuickGridViewPrivate::updateHeader() Q_Q(QQuickGridView); bool created = false; if (!header) { - QQuickItem *item = createComponentItem(headerComponent, true); + QQuickItem *item = createComponentItem(headerComponent); if (!item) return; item->setZ(1); - header = new FxGridItemSG(item, q, true); + header = new FxGridItemSG(item, q, true, true); created = true; } diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 5089d230d7..50a3216bf0 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -45,11 +45,12 @@ QT_BEGIN_NAMESPACE -FxViewItem::FxViewItem(QQuickItem *i, bool own) +FxViewItem::FxViewItem(QQuickItem *i, bool own, bool trackGeometry) : item(i) , transitionableItem(0) , ownItem(own) , releaseAfterTransition(false) + , trackGeom(trackGeometry) { } @@ -2195,10 +2196,10 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item) QQuickItem *QQuickItemViewPrivate::createHighlightItem() { - return createComponentItem(highlightComponent, true, true); + return createComponentItem(highlightComponent, true); } -QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault) +QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, bool createDefault) { Q_Q(QQuickItemView); @@ -2222,10 +2223,6 @@ QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, if (item) { QQml_setParent_noEvent(item, q->contentItem()); item->setParentItem(q->contentItem()); - if (receiveItemGeometryChanges) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry); - } } return item; } diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index dfc0a8bc7e..7516761ee8 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -60,7 +60,7 @@ QT_MODULE(Quick) class FxViewItem { public: - FxViewItem(QQuickItem *, bool own); + FxViewItem(QQuickItem *, bool own, bool trackGeometry); virtual ~FxViewItem(); qreal itemX() const; @@ -92,6 +92,7 @@ public: int index; bool ownItem; bool releaseAfterTransition; + bool trackGeom; }; @@ -124,6 +125,8 @@ public: QQuickItemViewPrivate(); ~QQuickItemViewPrivate(); + static inline QQuickItemViewPrivate *get(QQuickItemView *o) { return o->d_func(); } + struct ChangeResult { QQmlNullableValue visiblePos; bool changedFirstItem; @@ -191,7 +194,7 @@ public: virtual bool releaseItem(FxViewItem *item); QQuickItem *createHighlightItem(); - QQuickItem *createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault = false); + QQuickItem *createComponentItem(QQmlComponent *component, bool createDefault = false); void updateCurrent(int modelIndex); void updateTrackedItem(); diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 9d9e3ae186..6f33545185 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -236,13 +236,22 @@ void QQuickViewSection::setLabelPositioning(int l) class FxListItemSG : public FxViewItem { public: - FxListItemSG(QQuickItem *i, QQuickListView *v, bool own) : FxViewItem(i, own), view(v) { + FxListItemSG(QQuickItem *i, QQuickListView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) { attached = static_cast(qmlAttachedPropertiesObject(item)); if (attached) static_cast(attached)->setView(view); + if (trackGeometry) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } } - ~FxListItemSG() {} + ~FxListItemSG() { + if (trackGeom) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); + } + } inline QQuickItem *section() const { return attached ? static_cast(attached)->m_sectionItem : 0; @@ -536,7 +545,7 @@ FxViewItem *QQuickListViewPrivate::newViewItem(int modelIndex, QQuickItem *item) { Q_Q(QQuickListView); - FxListItemSG *listItem = new FxListItemSG(item, q, false); + FxListItemSG *listItem = new FxListItemSG(item, q, false, false); listItem->index = modelIndex; // initialise attached properties @@ -835,7 +844,7 @@ void QQuickListViewPrivate::createHighlight() if (currentItem) { QQuickItem *item = createHighlightItem(); if (item) { - FxListItemSG *newHighlight = new FxListItemSG(item, q, true); + FxListItemSG *newHighlight = new FxListItemSG(item, q, true, true); if (autoHighlight) { newHighlight->setSize(static_cast(currentItem)->itemSize()); @@ -1238,11 +1247,11 @@ void QQuickListViewPrivate::updateFooter() Q_Q(QQuickListView); bool created = false; if (!footer) { - QQuickItem *item = createComponentItem(footerComponent, true); + QQuickItem *item = createComponentItem(footerComponent); if (!item) return; item->setZ(1); - footer = new FxListItemSG(item, q, true); + footer = new FxListItemSG(item, q, true, true); created = true; } @@ -1269,11 +1278,11 @@ void QQuickListViewPrivate::updateHeader() Q_Q(QQuickListView); bool created = false; if (!header) { - QQuickItem *item = createComponentItem(headerComponent, true); + QQuickItem *item = createComponentItem(headerComponent); if (!item) return; item->setZ(1); - header = new FxListItemSG(item, q, true); + header = new FxListItemSG(item, q, true, true); created = true; } diff --git a/tests/auto/quick/qquickgridview/data/headerfooter.qml b/tests/auto/quick/qquickgridview/data/headerfooter.qml new file mode 100644 index 0000000000..322cfed388 --- /dev/null +++ b/tests/auto/quick/qquickgridview/data/headerfooter.qml @@ -0,0 +1,31 @@ +import QtQuick 2.0 + +GridView { + id: view + property bool horizontal: false + property bool rtl: false + width: 240 + height: 320 + + model: testModel + + flow: horizontal ? GridView.TopToBottom : GridView.LeftToRight + header: Rectangle { + objectName: "header" + width: horizontal ? 20 : view.width + height: horizontal ? view.height : 20 + color: "red" + } + footer: Rectangle { + objectName: "footer" + width: horizontal ? 30 : view.width + height: horizontal ? view.height : 30 + color: "blue" + } + + cellWidth: 80; + cellHeight: 80; + + delegate: Text { width: 80; height: 80; text: index + "(" + x + ")" } + layoutDirection: rtl ? Qt.RightToLeft : Qt.LeftToRight +} diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index a282d55ac8..88ed94d8bc 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -113,6 +113,7 @@ private slots: void footer_data(); void header(); void header_data(); + void headerFooter(); void resizeViewAndRepaint(); void changeColumnCount(); void indexAt_itemAt_data(); @@ -3144,6 +3145,151 @@ void tst_QQuickGridView::header_data() << QPointF(-(240 - 40), 0); } +class GVAccessor : public QQuickGridView +{ +public: + qreal minY() const { return minYExtent(); } + qreal maxY() const { return maxYExtent(); } + qreal minX() const { return minXExtent(); } + qreal maxX() const { return maxXExtent(); } +}; + +void tst_QQuickGridView::headerFooter() +{ + { + // Vertical + QQuickView *canvas = createView(); + + QmlListModel model; + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("headerfooter.qml")); + qApp->processEvents(); + + QQuickGridView *gridview = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(gridview != 0); + + QQuickItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickItem *header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), -header->height()); + + QQuickItem *footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 0.); + + QCOMPARE(static_cast(gridview)->minY(), header->height()); + QCOMPARE(static_cast(gridview)->maxY(), header->height()); + + delete canvas; + } + { + // Horizontal + QQuickView *canvas = createView(); + + QmlListModel model; + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("headerfooter.qml")); + canvas->rootObject()->setProperty("horizontal", true); + qApp->processEvents(); + + QQuickGridView *gridview = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(gridview != 0); + + QQuickItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickItem *header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->x(), -header->width()); + + QQuickItem *footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->x(), 0.); + + QCOMPARE(static_cast(gridview)->minX(), header->width()); + QCOMPARE(static_cast(gridview)->maxX(), header->width()); + + delete canvas; + } + { + // Horizontal RTL + QQuickView *canvas = createView(); + + QmlListModel model; + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("headerfooter.qml")); + canvas->rootObject()->setProperty("horizontal", true); + canvas->rootObject()->setProperty("rtl", true); + qApp->processEvents(); + + QQuickGridView *gridview = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(gridview != 0); + + QQuickItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickItem *header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->x(), 0.); + + QQuickItem *footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->x(), -footer->width()); + + QCOMPARE(static_cast(gridview)->minX(), 240. - header->width()); + QCOMPARE(static_cast(gridview)->maxX(), 240. - header->width()); + + delete canvas; + } + { + // Reset model + QQuickView *canvas = createView(); + + QaimModel model; + for (int i = 0; i < 6; i++) + model.addItem("Item" + QString::number(i), ""); + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("headerfooter.qml")); + qApp->processEvents(); + + QQuickGridView *gridview = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(gridview != 0); + + QQuickItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickItem *header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), -header->height()); + + QQuickItem *footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 80.*2); + + model.reset(); + + header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), -header->height()); + + footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 80.*2); + + delete canvas; + } +} + void tst_QQuickGridView::resizeViewAndRepaint() { QQuickView *canvas = createView(); diff --git a/tests/auto/quick/qquicklistview/data/headerfooter.qml b/tests/auto/quick/qquicklistview/data/headerfooter.qml index 8e8463d645..4c3eeca328 100644 --- a/tests/auto/quick/qquicklistview/data/headerfooter.qml +++ b/tests/auto/quick/qquicklistview/data/headerfooter.qml @@ -6,6 +6,8 @@ ListView { property bool rtl: false width: 240 height: 320 + + model: testModel orientation: horizontal ? ListView.Horizontal : ListView.Vertical header: Rectangle { diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 335fc3c6e2..202f5164af 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -3527,6 +3527,45 @@ void tst_QQuickListView::headerFooter() QCOMPARE(static_cast(listview)->minX(), 240. - header->width()); QCOMPARE(static_cast(listview)->maxX(), 240. - header->width()); + delete canvas; + } + { + // Reset model + QQuickView *canvas = createView(); + + QaimModel model; + for (int i = 0; i < 4; i++) + model.addItem("Item" + QString::number(i), ""); + QQmlContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(testFileUrl("headerfooter.qml")); + qApp->processEvents(); + + QQuickListView *listview = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(listview != 0); + + QQuickItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + QQuickItem *header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), -header->height()); + + QQuickItem *footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 30.*4); + + model.reset(); + + header = findItem(contentItem, "header"); + QVERIFY(header); + QCOMPARE(header->y(), -header->height()); + + footer = findItem(contentItem, "footer"); + QVERIFY(footer); + QCOMPARE(footer->y(), 30.*4); + delete canvas; } } -- cgit v1.2.3 From af3a8708b46e8ae6e177dcee028364bd9fd285cd Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 19 Mar 2012 17:37:02 +1000 Subject: When clearing an incubator also clear incubators it is waiting for. If an incubator is cleared while waiting for other incubators to complete also clear the incubators it is waiting for. Change-Id: I83470920c0fd8a23d0098849192555f7478bb492 Reviewed-by: Andrew den Exter --- src/qml/qml/qqmlincubator.cpp | 4 + tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp | 117 +++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index c8413f70ca..aa9777d89e 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -542,6 +542,10 @@ void QQmlIncubator::clear() d->clear(); + // if we're waiting on any incubators then they should be cleared too. + while (d->waitingFor.first()) + static_cast(d->waitingFor.first())->q->clear(); + d->vme.reset(); d->vmeGuard.clear(); diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index fc54f715c9..54a31aef1d 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -76,6 +76,7 @@ private slots: void nestedComponent(); void chainedAsynchronousIfNested(); void chainedAsynchronousIfNestedOnCompleted(); + void chainedAsynchronousClear(); void selfDelete(); void contextDelete(); @@ -934,6 +935,122 @@ void tst_qqmlincubator::chainedAsynchronousIfNestedOnCompleted() QVERIFY(incubator3.isReady()); } +// Checks that new AsynchronousIfNested incubators can be correctly cleared if started in +// componentCompleted(). +void tst_qqmlincubator::chainedAsynchronousClear() +{ + SelfRegisteringType::clearMe(); + + QQmlComponent component(&engine, testFileUrl("chainInCompletion.qml")); + QVERIFY(component.isReady()); + + QQmlComponent c1(&engine, testFileUrl("chainedAsynchronousIfNested.qml")); + QVERIFY(c1.isReady()); + + struct MyIncubator : public QQmlIncubator { + MyIncubator(MyIncubator *next, QQmlComponent *component, QQmlContext *ctxt) + : QQmlIncubator(AsynchronousIfNested), next(next), component(component), ctxt(ctxt) {} + + protected: + virtual void statusChanged(Status s) { + if (s == Ready && next) { + component->create(*next, 0, ctxt); + } + } + + private: + MyIncubator *next; + QQmlComponent *component; + QQmlContext *ctxt; + }; + + struct CallbackData { + CallbackData(QQmlComponent *c, MyIncubator *i, QQmlContext *ct) + : component(c), incubator(i), ctxt(ct) {} + QQmlComponent *component; + MyIncubator *incubator; + QQmlContext *ctxt; + static void callback(CompletionCallbackType *, void *data) { + CallbackData *d = (CallbackData *)data; + d->component->create(*d->incubator, 0, d->ctxt); + } + }; + + QQmlIncubator incubator(QQmlIncubator::Asynchronous); + component.create(incubator); + + QVERIFY(incubator.isLoading()); + QVERIFY(SelfRegisteringType::me() == 0); + + while (SelfRegisteringType::me() == 0 && incubator.isLoading()) { + bool b = false; + controller.incubateWhile(&b); + } + + QVERIFY(SelfRegisteringType::me() != 0); + QVERIFY(incubator.isLoading()); + + MyIncubator incubator3(0, &c1, qmlContext(SelfRegisteringType::me())); + MyIncubator incubator2(&incubator3, &c1, qmlContext(SelfRegisteringType::me())); + MyIncubator incubator1(&incubator2, &c1, qmlContext(SelfRegisteringType::me())); + + // start incubator1 in componentComplete + CallbackData cd(&c1, &incubator1, qmlContext(SelfRegisteringType::me())); + CompletionCallbackType::registerCallback(&CallbackData::callback, &cd); + + while (!incubator1.isLoading()) { + QVERIFY(incubator.isLoading()); + QVERIFY(incubator2.isNull()); + QVERIFY(incubator3.isNull()); + + bool b = false; + controller.incubateWhile(&b); + } + + QVERIFY(incubator.isLoading()); + QVERIFY(incubator1.isLoading()); + QVERIFY(incubator2.isNull()); + QVERIFY(incubator3.isNull()); + + while (incubator1.isLoading()) { + QVERIFY(incubator.isLoading()); + QVERIFY(incubator1.isLoading()); + QVERIFY(incubator2.isNull()); + QVERIFY(incubator3.isNull()); + + bool b = false; + controller.incubateWhile(&b); + } + + QVERIFY(incubator.isLoading()); + QVERIFY(incubator1.isReady()); + QVERIFY(incubator2.isLoading()); + QVERIFY(incubator3.isNull()); + + while (incubator2.isLoading()) { + QVERIFY(incubator.isLoading()); + QVERIFY(incubator1.isReady()); + QVERIFY(incubator2.isLoading()); + QVERIFY(incubator3.isNull()); + + bool b = false; + controller.incubateWhile(&b); + } + + QVERIFY(incubator.isLoading()); + QVERIFY(incubator1.isReady()); + QVERIFY(incubator2.isReady()); + QVERIFY(incubator3.isLoading()); + + // Any in loading state will become null when cleared. + incubator.clear(); + + QVERIFY(incubator.isNull()); + QVERIFY(incubator1.isReady()); + QVERIFY(incubator2.isReady()); + QVERIFY(incubator3.isNull()); +} + void tst_qqmlincubator::selfDelete() { struct MyIncubator : public QQmlIncubator { -- cgit v1.2.3 From cad5df2572d023d1d8ab213d7e736f8d15576916 Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Mon, 12 Mar 2012 14:08:56 +0100 Subject: QmlDebugging: Object Tree and States List All created instances are stored under the root context. Check for the creation context of the object when building up the tree. Do the same when building up the states list. Change-Id: I8716d9966a61b8f7cb3ad4b7ab5acd4c94b4cd03 Reviewed-by: Kai Koehne --- src/qml/debugger/qqmldebugstatesdelegate_p.h | 5 ++- src/qml/debugger/qqmlenginedebugservice.cpp | 44 ++++++++++++++-------- src/qml/debugger/qqmlenginedebugservice_p.h | 6 ++- src/quick/qtquick2.cpp | 17 +++------ .../tst_qqmlenginedebugservice.cpp | 29 +++++++------- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/qml/debugger/qqmldebugstatesdelegate_p.h b/src/qml/debugger/qqmldebugstatesdelegate_p.h index 6e3cc978f2..6d4ac10dbf 100644 --- a/src/qml/debugger/qqmldebugstatesdelegate_p.h +++ b/src/qml/debugger/qqmldebugstatesdelegate_p.h @@ -54,6 +54,8 @@ // #include +#include +#include QT_BEGIN_HEADER @@ -74,7 +76,8 @@ protected: public: virtual ~QQmlDebugStatesDelegate() {} - virtual void buildStatesList(QQmlContext *ctxt, bool cleanList) = 0; + virtual void buildStatesList(bool cleanList, + const QList > &instances) = 0; virtual void updateBinding(QQmlContext *context, const QQmlProperty &property, const QVariant &expression, bool isLiteralValue, diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 892098bd93..7f9e38bd79 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -297,7 +297,9 @@ void QQmlEngineDebugService::prepareDeferredObjects(QObject *obj) } -void QQmlEngineDebugService::buildObjectList(QDataStream &message, QQmlContext *ctxt) +void QQmlEngineDebugService::buildObjectList(QDataStream &message, + QQmlContext *ctxt, + const QList > &instances) { QQmlContextData *p = QQmlContextData::get(ctxt); @@ -318,29 +320,30 @@ void QQmlEngineDebugService::buildObjectList(QDataStream &message, QQmlContext * child = p->childContexts; while (child) { - buildObjectList(message, child->asQQmlContext()); + buildObjectList(message, child->asQQmlContext(), instances); child = child->nextChild; } - // Clean deleted objects - QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(ctxt); - for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { - if (!ctxtPriv->instances.at(ii)) { - ctxtPriv->instances.removeAt(ii); - --ii; - } + count = 0; + for (int ii = 0; ii < instances.count(); ++ii) { + QQmlData *data = QQmlData::get(instances.at(ii)); + if (data->context == p) + count ++; } + message << count; - message << ctxtPriv->instances.count(); - for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { - message << objectData(ctxtPriv->instances.at(ii)); + for (int ii = 0; ii < instances.count(); ++ii) { + QQmlData *data = QQmlData::get(instances.at(ii)); + if (data->context == p) + message << objectData(instances.at(ii)); } } -void QQmlEngineDebugService::buildStatesList(QQmlContext *ctxt, bool cleanList) +void QQmlEngineDebugService::buildStatesList(bool cleanList, + const QList > &instances) { if (m_statesDelegate) - m_statesDelegate->buildStatesList(ctxt, cleanList); + m_statesDelegate->buildStatesList(cleanList, instances); } QQmlEngineDebugService::QQmlObjectData @@ -427,8 +430,17 @@ void QQmlEngineDebugService::processMessage(const QByteArray &message) rs << QByteArray("LIST_OBJECTS_R") << queryId; if (engine) { - buildObjectList(rs, engine->rootContext()); - buildStatesList(engine->rootContext(), true); + QQmlContext *rootContext = engine->rootContext(); + // Clean deleted objects + QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + if (!ctxtPriv->instances.at(ii)) { + ctxtPriv->instances.removeAt(ii); + --ii; + } + } + buildObjectList(rs, rootContext, ctxtPriv->instances); + buildStatesList(true, ctxtPriv->instances); } sendMessage(reply); diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h index 1a92801fcc..f41063d7a3 100644 --- a/src/qml/debugger/qqmlenginedebugservice_p.h +++ b/src/qml/debugger/qqmlenginedebugservice_p.h @@ -57,6 +57,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -111,9 +112,10 @@ private Q_SLOTS: private: void prepareDeferredObjects(QObject *); - void buildObjectList(QDataStream &, QQmlContext *); + void buildObjectList(QDataStream &, QQmlContext *, + const QList > &instances); void buildObjectDump(QDataStream &, QObject *, bool, bool); - void buildStatesList(QQmlContext *, bool); + void buildStatesList(bool cleanList, const QList > &instances); QQmlObjectData objectData(QObject *); QQmlObjectProperty propertyData(QObject *, int); QVariant valueContents(const QVariant &defaultValue) const; diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp index 32a9d382f2..a97dade106 100644 --- a/src/quick/qtquick2.cpp +++ b/src/quick/qtquick2.cpp @@ -63,7 +63,7 @@ class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate public: QQmlQtQuick2DebugStatesDelegate(); virtual ~QQmlQtQuick2DebugStatesDelegate(); - virtual void buildStatesList(QQmlContext *ctxt, bool cleanList); + virtual void buildStatesList(bool cleanList, const QList > &instances); virtual void updateBinding(QQmlContext *context, const QQmlProperty &property, const QVariant &expression, bool isLiteralValue, @@ -90,20 +90,15 @@ QQmlQtQuick2DebugStatesDelegate::~QQmlQtQuick2DebugStatesDelegate() { } -void QQmlQtQuick2DebugStatesDelegate::buildStatesList(QQmlContext *ctxt, bool cleanList) +void QQmlQtQuick2DebugStatesDelegate::buildStatesList(bool cleanList, + const QList > &instances) { if (cleanList) m_allStates.clear(); - QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(ctxt); - for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { - buildStatesList(ctxtPriv->instances.at(ii)); - } - - QQmlContextData *child = QQmlContextData::get(ctxt)->childContexts; - while (child) { - buildStatesList(child->asQQmlContext()); - child = child->nextChild; + //only root context has all instances + for (int ii = 0; ii < instances.count(); ++ii) { + buildStatesList(instances.at(ii)); } } diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 9756313905..e409f3c8b6 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -137,11 +137,15 @@ QQmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(int context, QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); - if (q_context->rootContext().objects().count() == 0) + if (q_context->rootContext().contexts().count() == 0 || + q_context->rootContext().contexts().last().objects().count() == 0) return QQmlDebugObjectReference(); + + //Contexts are in a stack + int count = q_context->rootContext().contexts().count(); QQmlDebugObjectQuery *q_obj = recursive ? - m_dbg->queryObjectRecursive(q_context->rootContext().objects()[context], this) : - m_dbg->queryObject(q_context->rootContext().objects()[context], this); + m_dbg->queryObjectRecursive(q_context->rootContext().contexts()[count - context - 1].objects()[0], this) : + m_dbg->queryObject(q_context->rootContext().contexts()[count - context - 1].objects()[0], this); waitForQuery(q_obj); QQmlDebugObjectReference result = q_obj->object(); @@ -493,8 +497,9 @@ void tst_QQmlEngineDebugService::watch_object() QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); - QVERIFY(q_context->rootContext().objects().count() > 0); - QQmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this); + QVERIFY(q_context->rootContext().contexts().count()); + QVERIFY(q_context->rootContext().contexts().last().objects().count() > 0); + QQmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().contexts().last().objects()[0], this); waitForQuery(q_obj); QQmlDebugObjectReference obj = q_obj->object(); @@ -705,12 +710,9 @@ void tst_QQmlEngineDebugService::queryRootContexts() QCOMPARE(context.debugId(), QQmlDebugService::idForObject(actualContext)); QCOMPARE(context.name(), actualContext->objectName()); - QCOMPARE(context.objects().count(), 4); // 4 qml component objects created for context in main() - // root context query sends only root object data - it doesn't fill in // the children or property info - QCOMPARE(context.objects()[0].properties().count(), 0); - QCOMPARE(context.objects()[0].children().count(), 0); + QCOMPARE(context.objects().count(), 0); QCOMPARE(context.contexts().count(), 5); QVERIFY(context.contexts()[0].debugId() >= 0); @@ -734,7 +736,7 @@ void tst_QQmlEngineDebugService::queryObject() QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); - QQmlDebugObjectReference rootObject = q_context->rootContext().objects()[0]; + QQmlDebugObjectReference rootObject = q_context->rootContext().contexts().last().objects()[0]; QQmlDebugObjectQuery *q_obj = 0; @@ -815,7 +817,7 @@ void tst_QQmlEngineDebugService::queryExpressionResult() QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); - int objectId = q_context->rootContext().objects()[0].debugId(); + int objectId = q_context->rootContext().contexts().last().objects()[0].debugId(); QQmlDebugExpressionQuery *q_expr; @@ -1164,8 +1166,9 @@ void tst_QQmlEngineDebugService::queryObjectTree() QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); waitForQuery(q_context); - QVERIFY(q_context->rootContext().objects().count() > sourceIndex); - QQmlDebugObjectReference rootObject = q_context->rootContext().objects()[sourceIndex]; + QVERIFY(q_context->rootContext().contexts().count() >= sourceIndex); + int count = q_context->rootContext().contexts().count(); + QQmlDebugObjectReference rootObject = q_context->rootContext().contexts()[count - sourceIndex - 1].objects()[0]; QQmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(rootObject, this); waitForQuery(q_obj); -- cgit v1.2.3 From 341f74356962faae682f6ede218e4e45aa959e13 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 16 Mar 2012 14:05:05 +0100 Subject: Debugger: Fix compilation with C++11 Change-Id: I6f753d14aa381fd29aadfc7c649599beb4ec4a9a Reviewed-by: Thiago Macieira --- src/qml/debugger/qqmlenginedebugservice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 7f9e38bd79..a89e94c1b8 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -211,7 +211,7 @@ QVariant QQmlEngineDebugService::valueContents(const QVariant &value) const } } - return QStringLiteral(""); + return QString(QStringLiteral("")); } void QQmlEngineDebugService::buildObjectDump(QDataStream &message, -- cgit v1.2.3 From 26d5f2e833f0e3686aaa27e695bbfab5fbd808ad Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Mon, 19 Mar 2012 12:19:53 +1000 Subject: Notify QQJSE::DW of expression deletion during dtor QQmlJavaScriptExpression::DeleteWatcher's wasDeleted() function simply checks to see if the pointer to the expression being watched is null. This commit ensures that the DeleteWatcher's expression pointer is set to null during QQJSE::dtor(). Change-Id: I566737bf30b4466ba96d771d9846fc3dd860cd2f Reviewed-by: Michael Brasser --- src/qml/qml/qqmljavascriptexpression.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 560e0f1342..aad6a04714 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -69,6 +69,8 @@ QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) QQmlJavaScriptExpression::~QQmlJavaScriptExpression() { clearGuards(); + if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion. + m_scopeObject.asT2()->_s = 0; } void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) -- cgit v1.2.3