aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
commitd77218522eb480c8d528de18049cd7b604cdeb2a (patch)
treea6433a8e9205a95006eae10b53285a0e3487423d /src
parent589c8445e2623ef8e0b8294d7c558a2948b2a5e3 (diff)
parentd5686fa2ac2248d5a31237573fa08697f18f035f (diff)
Merge branch 'master' into refactor
Conflicts: examples/declarative/cppextensions/qwidgets/qwidgets.pro examples/declarative/minehunt/main.cpp examples/declarative/minehunt/minehunt.pro src/declarative/items/context2d/qsgcontext2d.cpp src/declarative/items/qsgflickable.cpp src/declarative/items/qsgtextedit.cpp src/declarative/items/qsgtextinput.cpp src/declarative/particles/qsgangleddirection.cpp src/declarative/particles/qsgcumulativedirection.cpp src/declarative/particles/qsgcumulativedirection_p.h src/declarative/particles/qsgfollowemitter.cpp src/declarative/particles/qsgmodelparticle.cpp src/declarative/particles/qsgparticlesystem.cpp src/qtquick1/util/qdeclarativeview.h tests/auto/declarative/examples/examples.pro tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp Change-Id: Ib4be2a5e742dee1a399d73da97161736f77448e5
Diffstat (limited to 'src')
-rw-r--r--src/declarative/debugger/debugger.pri11
-rw-r--r--src/declarative/debugger/qdeclarativedebug.h67
-rw-r--r--src/declarative/debugger/qdeclarativedebugclient.cpp118
-rw-r--r--src/declarative/debugger/qdeclarativedebugclient_p.h33
-rw-r--r--src/declarative/debugger/qdeclarativedebuggerstatus_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebughelper_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp10
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebugserverconnection_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice.cpp42
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebugservice_p_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace.cpp16
-rw-r--r--src/declarative/debugger/qdeclarativedebugtrace_p.h11
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebug.cpp (renamed from src/declarative/debugger/qdeclarativedebug.cpp)116
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebug_p.h (renamed from src/declarative/debugger/qdeclarativedebug_p.h)59
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice.cpp (renamed from src/declarative/qml/qdeclarativeenginedebug.cpp)104
-rw-r--r--src/declarative/debugger/qdeclarativeenginedebugservice_p.h (renamed from src/declarative/qml/qdeclarativeenginedebug_p.h)20
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorinterface_p.h17
-rw-r--r--src/declarative/debugger/qdeclarativeinspectorservice_p.h17
-rw-r--r--src/declarative/debugger/qpacketprotocol.cpp56
-rw-r--r--src/declarative/debugger/qpacketprotocol_p.h25
-rw-r--r--src/declarative/debugger/qv8debugservice.cpp7
-rw-r--r--src/declarative/declarative.pro1
-rw-r--r--src/declarative/designer/designer.pri2
-rw-r--r--src/declarative/designer/designersupport.cpp408
-rw-r--r--src/declarative/designer/designersupport.h149
-rw-r--r--src/declarative/items/context2d/qsgcontext2d.cpp587
-rw-r--r--src/declarative/items/qsganimation.cpp228
-rw-r--r--src/declarative/items/qsganimation_p.h62
-rw-r--r--src/declarative/items/qsganimation_p_p.h41
-rw-r--r--src/declarative/items/qsgcanvas.cpp2
-rw-r--r--src/declarative/items/qsgflickable.cpp21
-rw-r--r--src/declarative/items/qsgflickable_p.h6
-rw-r--r--src/declarative/items/qsgflickable_p_p.h1
-rw-r--r--src/declarative/items/qsggridview.cpp386
-rw-r--r--src/declarative/items/qsggridview_p.h5
-rw-r--r--src/declarative/items/qsgimagebase.cpp6
-rw-r--r--src/declarative/items/qsgimagebase_p.h2
-rw-r--r--src/declarative/items/qsgitem.cpp24
-rw-r--r--src/declarative/items/qsgitem.h6
-rw-r--r--src/declarative/items/qsgitem_p.h2
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp10
-rw-r--r--src/declarative/items/qsgitemview.cpp376
-rw-r--r--src/declarative/items/qsgitemview_p.h6
-rw-r--r--src/declarative/items/qsgitemview_p_p.h42
-rw-r--r--src/declarative/items/qsglistview.cpp423
-rw-r--r--src/declarative/items/qsglistview_p.h5
-rw-r--r--src/declarative/items/qsgshadereffect.cpp72
-rw-r--r--src/declarative/items/qsgshadereffect_p.h2
-rw-r--r--src/declarative/items/qsgshadereffectmesh.cpp42
-rw-r--r--src/declarative/items/qsgshadereffectmesh_p.h2
-rw-r--r--src/declarative/items/qsgtext.cpp13
-rw-r--r--src/declarative/items/qsgtextedit.cpp1
-rw-r--r--src/declarative/items/qsgtextinput.cpp3
-rw-r--r--src/declarative/items/qsgview.h3
-rw-r--r--src/declarative/particles/particles.pri30
-rw-r--r--src/declarative/particles/qsgage.cpp81
-rw-r--r--src/declarative/particles/qsgage_p.h87
-rw-r--r--src/declarative/particles/qsgangledirection.cpp (renamed from src/declarative/particles/qsgangleddirection.cpp)22
-rw-r--r--src/declarative/particles/qsgangledirection_p.h (renamed from src/declarative/particles/qsgangleddirection_p.h)6
-rw-r--r--src/declarative/particles/qsgcumulativedirection.cpp16
-rw-r--r--src/declarative/particles/qsgcumulativedirection_p.h11
-rw-r--r--src/declarative/particles/qsgcustomaffector.cpp80
-rw-r--r--src/declarative/particles/qsgcustomaffector_p.h (renamed from src/declarative/particles/qsgkill_p.h)26
-rw-r--r--src/declarative/particles/qsgcustomparticle.cpp107
-rw-r--r--src/declarative/particles/qsgdirection.cpp (renamed from src/declarative/particles/qsgstochasticdirection.cpp)10
-rw-r--r--src/declarative/particles/qsgdirection_p.h (renamed from src/declarative/particles/qsgstochasticdirection_p.h)4
-rw-r--r--src/declarative/particles/qsgfriction.cpp2
-rw-r--r--src/declarative/particles/qsggravity.cpp8
-rw-r--r--src/declarative/particles/qsgimageparticle.cpp119
-rw-r--r--src/declarative/particles/qsgimageparticle_p.h22
-rw-r--r--src/declarative/particles/qsgitemparticle.cpp43
-rw-r--r--src/declarative/particles/qsgmaskextruder.cpp3
-rw-r--r--src/declarative/particles/qsgmodelparticle.cpp298
-rw-r--r--src/declarative/particles/qsgmodelparticle_p.h140
-rw-r--r--src/declarative/particles/qsgparticleaffector.cpp69
-rw-r--r--src/declarative/particles/qsgparticleaffector_p.h62
-rw-r--r--src/declarative/particles/qsgparticleemitter.cpp88
-rw-r--r--src/declarative/particles/qsgparticleemitter_p.h193
-rw-r--r--src/declarative/particles/qsgparticleextruder.cpp22
-rw-r--r--src/declarative/particles/qsgparticleextruder_p.h19
-rw-r--r--src/declarative/particles/qsgparticlepainter.cpp4
-rw-r--r--src/declarative/particles/qsgparticlesmodule.cpp34
-rw-r--r--src/declarative/particles/qsgparticlesystem.cpp411
-rw-r--r--src/declarative/particles/qsgparticlesystem_p.h55
-rw-r--r--src/declarative/particles/qsgpointattractor.cpp61
-rw-r--r--src/declarative/particles/qsgpointattractor_p.h20
-rw-r--r--src/declarative/particles/qsgpointdirection.cpp4
-rw-r--r--src/declarative/particles/qsgpointdirection_p.h4
-rw-r--r--src/declarative/particles/qsgrectangleextruder.cpp86
-rw-r--r--src/declarative/particles/qsgrectangleextruder_p.h88
-rw-r--r--src/declarative/particles/qsgtargetdirection.cpp (renamed from src/declarative/particles/qsgtargeteddirection.cpp)28
-rw-r--r--src/declarative/particles/qsgtargetdirection_p.h (renamed from src/declarative/particles/qsgtargeteddirection_p.h)6
-rw-r--r--src/declarative/particles/qsgtrailemitter.cpp (renamed from src/declarative/particles/qsgfollowemitter.cpp)48
-rw-r--r--src/declarative/particles/qsgtrailemitter_p.h (renamed from src/declarative/particles/qsgfollowemitter_p.h)7
-rw-r--r--src/declarative/particles/qsgturbulence.cpp2
-rw-r--r--src/declarative/particles/qsgv8particledata.cpp58
-rw-r--r--src/declarative/particles/qsgwander.cpp33
-rw-r--r--src/declarative/particles/qsgwander_p.h22
-rw-r--r--src/declarative/qml/ftw/qdeclarativepool.cpp34
-rw-r--r--src/declarative/qml/ftw/qdeclarativepool_p.h34
-rw-r--r--src/declarative/qml/ftw/qdeclarativeutils_p.h34
-rw-r--r--src/declarative/qml/ftw/qfieldlist_p.h34
-rw-r--r--src/declarative/qml/ftw/qmetaobjectbuilder.cpp10
-rw-r--r--src/declarative/qml/qdeclarative.h11
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp2
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp4
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp34
-rw-r--r--src/declarative/qml/qdeclarativeengine.h1
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp2
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp33
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h5
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp2
-rw-r--r--src/declarative/qml/qml.pri2
-rw-r--r--src/declarative/qml/v8/qscripttools_p.h4
-rw-r--r--src/declarative/qml/v8/qv8debug_p.h41
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp142
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h3
-rw-r--r--src/declarative/qml/v8/qv8gccallback_p.h112
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp57
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper_p.h2
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp28
-rw-r--r--src/declarative/qml/v8/qv8typewrapper_p.h1
-rw-r--r--src/declarative/qml/v8/v8.pri1
-rw-r--r--src/declarative/util/qdeclarativepath.cpp661
-rw-r--r--src/declarative/util/qdeclarativepath_p.h181
-rw-r--r--src/declarative/util/qdeclarativepath_p_p.h13
-rw-r--r--src/declarative/util/qdeclarativepathinterpolator.cpp122
-rw-r--r--src/declarative/util/qdeclarativepathinterpolator_p.h100
-rw-r--r--src/declarative/util/qdeclarativepropertymap.cpp28
-rw-r--r--src/declarative/util/qdeclarativestyledtext.cpp289
-rw-r--r--src/declarative/util/qdeclarativesvgparser.cpp633
-rw-r--r--src/declarative/util/qdeclarativesvgparser_p.h (renamed from src/declarative/particles/qsgkill.cpp)36
-rw-r--r--src/declarative/util/qdeclarativetransitionmanager.cpp7
-rw-r--r--src/declarative/util/util.pri8
-rw-r--r--src/imports/testlib/TestCase.qml3
-rw-r--r--src/qmltest/quicktestresult.cpp40
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextedit.cpp11
-rw-r--r--src/qtquick1/graphicsitems/qdeclarativetextinput.cpp9
-rw-r--r--src/qtquick1/util/qdeclarativeview.h1
141 files changed, 6120 insertions, 2928 deletions
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index e7462d4e78..a257da216f 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -5,12 +5,13 @@ SOURCES += \
$$PWD/qpacketprotocol.cpp \
$$PWD/qdeclarativedebugservice.cpp \
$$PWD/qdeclarativedebugclient.cpp \
- $$PWD/qdeclarativedebug.cpp \
+ $$PWD/qdeclarativeenginedebug.cpp \
$$PWD/qdeclarativedebugtrace.cpp \
$$PWD/qdeclarativedebughelper.cpp \
$$PWD/qdeclarativedebugserver.cpp \
$$PWD/qdeclarativeinspectorservice.cpp \
- $$PWD/qv8debugservice.cpp
+ $$PWD/qv8debugservice.cpp \
+ $$PWD/qdeclarativeenginedebugservice.cpp
HEADERS += \
$$PWD/qdeclarativedebuggerstatus_p.h \
@@ -18,11 +19,13 @@ HEADERS += \
$$PWD/qdeclarativedebugservice_p.h \
$$PWD/qdeclarativedebugservice_p_p.h \
$$PWD/qdeclarativedebugclient_p.h \
- $$PWD/qdeclarativedebug_p.h \
+ $$PWD/qdeclarativeenginedebug_p.h \
$$PWD/qdeclarativedebugtrace_p.h \
$$PWD/qdeclarativedebughelper_p.h \
$$PWD/qdeclarativedebugserver_p.h \
$$PWD/qdeclarativedebugserverconnection_p.h \
$$PWD/qdeclarativeinspectorservice_p.h \
$$PWD/qdeclarativeinspectorinterface_p.h \
- $$PWD/qv8debugservice_p.h
+ $$PWD/qv8debugservice_p.h \
+ $$PWD/qdeclarativeenginedebugservice_p.h \
+ $$PWD/qdeclarativedebug.h
diff --git a/src/declarative/debugger/qdeclarativedebug.h b/src/declarative/debugger/qdeclarativedebug.h
new file mode 100644
index 0000000000..b7930b21f0
--- /dev/null
+++ b/src/declarative/debugger/qdeclarativedebug.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QDECLARATIVEDEBUG_H
+#define QDECLARATIVEDEBUG_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+struct Q_DECLARATIVE_EXPORT QDeclarativeDebuggingEnabler
+{
+ QDeclarativeDebuggingEnabler();
+};
+
+// Execute code in constructor before first QDeclarativeEngine is instantiated
+#if defined(QT_DECLARATIVE_DEBUG)
+static QDeclarativeDebuggingEnabler qmlEnableDebuggingHelper;
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEDEBUG_H
diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp
index d3617b19b5..606ad2deae 100644
--- a/src/declarative/debugger/qdeclarativedebugclient.cpp
+++ b/src/declarative/debugger/qdeclarativedebugclient.cpp
@@ -45,6 +45,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
+#include <QtNetwork/qnetworkproxy.h>
#include <private/qobject_p.h>
@@ -71,20 +72,23 @@ public:
QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c);
QDeclarativeDebugConnection *q;
QPacketProtocol *protocol;
+ QIODevice *device;
bool gotHello;
QStringList serverPlugins;
QHash<QString, QDeclarativeDebugClient *> plugins;
void advertisePlugins();
+ void connectDeviceSignals();
public Q_SLOTS:
void connected();
void readyRead();
+ void deviceAboutToClose();
};
QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c)
-: QObject(c), q(c), protocol(0), gotHello(false)
+ : QObject(c), q(c), protocol(0), device(0), gotHello(false)
{
protocol = new QPacketProtocol(q, this);
QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
@@ -137,7 +141,6 @@ void QDeclarativeDebugConnectionPrivate::readyRead()
QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
return;
}
-
gotHello = true;
QHash<QString, QDeclarativeDebugClient *>::Iterator iter = plugins.begin();
@@ -183,7 +186,7 @@ void QDeclarativeDebugConnectionPrivate::readyRead()
pack >> message;
QHash<QString, QDeclarativeDebugClient *>::Iterator iter =
- plugins.find(name);
+ plugins.find(name);
if (iter == plugins.end()) {
qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name;
} else {
@@ -193,8 +196,15 @@ void QDeclarativeDebugConnectionPrivate::readyRead()
}
}
+void QDeclarativeDebugConnectionPrivate::deviceAboutToClose()
+{
+ // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close())
+ // without calling the underlying device close fn as that would cause an infinite loop
+ q->QIODevice::close();
+}
+
QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent)
-: QTcpSocket(parent), d(new QDeclarativeDebugConnectionPrivate(this))
+ : QIODevice(parent), d(new QDeclarativeDebugConnectionPrivate(this))
{
}
@@ -202,24 +212,107 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection()
{
QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter) {
- iter.value()->d_func()->connection = 0;
- iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
+ iter.value()->d_func()->connection = 0;
+ iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
}
}
bool QDeclarativeDebugConnection::isConnected() const
{
- return state() == ConnectedState;
+ return state() == QAbstractSocket::ConnectedState;
+}
+
+qint64 QDeclarativeDebugConnection::readData(char *data, qint64 maxSize)
+{
+ return d->device->read(data, maxSize);
+}
+
+qint64 QDeclarativeDebugConnection::writeData(const char *data, qint64 maxSize)
+{
+ return d->device->write(data, maxSize);
+}
+
+qint64 QDeclarativeDebugConnection::bytesAvailable() const
+{
+ return d->device->bytesAvailable();
+}
+
+bool QDeclarativeDebugConnection::isSequential() const
+{
+ return true;
}
+void QDeclarativeDebugConnection::close()
+{
+ if (isOpen()) {
+ QIODevice::close();
+ d->device->close();
+ emit stateChanged(QAbstractSocket::UnconnectedState);
+
+ QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected);
+ }
+ }
+}
+
+bool QDeclarativeDebugConnection::waitForConnected(int msecs)
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket)
+ return socket->waitForConnected(msecs);
+ return false;
+}
+
+QAbstractSocket::SocketState QDeclarativeDebugConnection::state() const
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket)
+ return socket->state();
+
+ return QAbstractSocket::UnconnectedState;
+}
+
+void QDeclarativeDebugConnection::flush()
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket) {
+ socket->flush();
+ return;
+ }
+}
+
+void QDeclarativeDebugConnection::connectToHost(const QString &hostName, quint16 port)
+{
+ QTcpSocket *socket = new QTcpSocket(d);
+ socket->setProxy(QNetworkProxy::NoProxy);
+ d->device = socket;
+ d->connectDeviceSignals();
+ d->gotHello = false;
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(error(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(connected()), this, SIGNAL(connected()));
+ socket->connectToHost(hostName, port);
+ QIODevice::open(ReadWrite | Unbuffered);
+}
+
+void QDeclarativeDebugConnectionPrivate::connectDeviceSignals()
+{
+ connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)));
+ connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead()));
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose()));
+}
+
+//
+
QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate()
-: connection(0)
+ : connection(0)
{
}
QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name,
- QDeclarativeDebugConnection *parent)
-: QObject(*(new QDeclarativeDebugClientPrivate), parent)
+ QDeclarativeDebugConnection *parent)
+ : QObject(*(new QDeclarativeDebugClientPrivate), parent)
{
Q_D(QDeclarativeDebugClient);
d->name = name;
@@ -239,7 +332,7 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name,
QDeclarativeDebugClient::~QDeclarativeDebugClient()
{
- Q_D(const QDeclarativeDebugClient);
+ Q_D(QDeclarativeDebugClient);
if (d->connection && d->connection->d) {
d->connection->d->plugins.remove(d->name);
d->connection->d->advertisePlugins();
@@ -269,14 +362,13 @@ QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const
void QDeclarativeDebugClient::sendMessage(const QByteArray &message)
{
Q_D(QDeclarativeDebugClient);
-
if (status() != Enabled)
return;
QPacket pack;
pack << d->name << message;
d->connection->d->protocol->send(pack);
- d->connection->d->q->flush();
+ d->connection->flush();
}
void QDeclarativeDebugClient::statusChanged(Status)
diff --git a/src/declarative/debugger/qdeclarativedebugclient_p.h b/src/declarative/debugger/qdeclarativedebugclient_p.h
index a2648d61c2..5b219358ff 100644
--- a/src/declarative/debugger/qdeclarativedebugclient_p.h
+++ b/src/declarative/debugger/qdeclarativedebugclient_p.h
@@ -42,6 +42,17 @@
#ifndef QDECLARATIVEDEBUGCLIENT_H
#define QDECLARATIVEDEBUGCLIENT_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 <QtNetwork/qtcpsocket.h>
#include <private/qdeclarativeglobal_p.h>
@@ -53,7 +64,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QDeclarativeDebugConnectionPrivate;
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugConnection : public QTcpSocket
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugConnection : public QIODevice
{
Q_OBJECT
Q_DISABLE_COPY(QDeclarativeDebugConnection)
@@ -61,7 +72,25 @@ public:
QDeclarativeDebugConnection(QObject * = 0);
~QDeclarativeDebugConnection();
+ void connectToHost(const QString &hostName, quint16 port);
+
+ qint64 bytesAvailable() const;
bool isConnected() const;
+ QAbstractSocket::SocketState state() const;
+ void flush();
+ bool isSequential() const;
+ void close();
+ bool waitForConnected(int msecs = 30000);
+
+signals:
+ void connected();
+ void stateChanged(QAbstractSocket::SocketState socketState);
+ void error(QAbstractSocket::SocketError socketError);
+
+protected:
+ qint64 readData(char *data, qint64 maxSize);
+ qint64 writeData(const char *data, qint64 maxSize);
+
private:
QDeclarativeDebugConnectionPrivate *d;
friend class QDeclarativeDebugClient;
@@ -85,7 +114,7 @@ public:
Status status() const;
- void sendMessage(const QByteArray &);
+ virtual void sendMessage(const QByteArray &);
protected:
virtual void statusChanged(Status);
diff --git a/src/declarative/debugger/qdeclarativedebuggerstatus_p.h b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h
index 7904a06af6..385301e62d 100644
--- a/src/declarative/debugger/qdeclarativedebuggerstatus_p.h
+++ b/src/declarative/debugger/qdeclarativedebuggerstatus_p.h
@@ -42,6 +42,17 @@
#ifndef QDECLARATIVEDEBUGGERSTATUS_P_H
#define QDECLARATIVEDEBUGGERSTATUS_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qobject.h>
#include <private/qdeclarativeglobal_p.h>
diff --git a/src/declarative/debugger/qdeclarativedebughelper_p.h b/src/declarative/debugger/qdeclarativedebughelper_p.h
index d9ed5796ee..b92f3ba975 100644
--- a/src/declarative/debugger/qdeclarativedebughelper_p.h
+++ b/src/declarative/debugger/qdeclarativedebughelper_p.h
@@ -46,6 +46,17 @@
#include <private/qdeclarativeglobal_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.
+//
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index 6e2db4f605..8bda0062f9 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -120,7 +120,7 @@ void QDeclarativeDebugServerPrivate::advertisePlugins()
}
QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
- const QString &pluginName)
+ const QString &pluginName)
{
QStringList pluginCandidates;
const QStringList paths = QCoreApplication::libraryPaths();
@@ -178,9 +178,9 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
if (!appD->qmljsDebugArgumentsString().isEmpty()) {
if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
const QString message =
- QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
- "Debugging has not been enabled.").arg(
- appD->qmljsDebugArgumentsString());
+ QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "Debugging has not been enabled.").arg(
+ appD->qmljsDebugArgumentsString());
qWarning("%s", qPrintable(message));
return 0;
}
@@ -231,7 +231,7 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
}
QDeclarativeDebugServer::QDeclarativeDebugServer()
-: QObject(*(new QDeclarativeDebugServerPrivate))
+ : QObject(*(new QDeclarativeDebugServerPrivate))
{
}
diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h
index 53c1077c7b..d80633cd7d 100644
--- a/src/declarative/debugger/qdeclarativedebugserver_p.h
+++ b/src/declarative/debugger/qdeclarativedebugserver_p.h
@@ -45,6 +45,17 @@
#include <private/qdeclarativeglobal_p.h>
#include <private/qdeclarativedebugserverconnection_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.
+//
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
index d7f0de62fa..832224ea33 100644
--- a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
+++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h
@@ -44,6 +44,17 @@
#include <QtDeclarative/private/qdeclarativeglobal_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.
+//
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp
index 7274211bf2..ecd9e0fb85 100644
--- a/src/declarative/debugger/qdeclarativedebugservice.cpp
+++ b/src/declarative/debugger/qdeclarativedebugservice.cpp
@@ -49,12 +49,12 @@
QT_BEGIN_NAMESPACE
QDeclarativeDebugServicePrivate::QDeclarativeDebugServicePrivate()
-: server(0)
+ : server(0)
{
}
QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject *parent)
-: QObject(*(new QDeclarativeDebugServicePrivate), parent)
+ : QObject(*(new QDeclarativeDebugServicePrivate), parent)
{
Q_D(QDeclarativeDebugService);
d->name = name;
@@ -114,21 +114,21 @@ QDeclarativeDebugService::Status QDeclarativeDebugService::status() const
namespace {
- struct ObjectReference
- {
- QPointer<QObject> object;
- int id;
- };
+struct ObjectReference
+{
+ QPointer<QObject> object;
+ int id;
+};
- struct ObjectReferenceHash
- {
- ObjectReferenceHash() : nextId(0) {}
+struct ObjectReferenceHash
+{
+ ObjectReferenceHash() : nextId(0) {}
- QHash<QObject *, ObjectReference> objects;
- QHash<int, QObject *> ids;
+ QHash<QObject *, ObjectReference> objects;
+ QHash<int, QObject *> ids;
- int nextId;
- };
+ int nextId;
+};
}
Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash);
@@ -144,8 +144,8 @@ int QDeclarativeDebugService::idForObject(QObject *object)
return -1;
ObjectReferenceHash *hash = objectReferenceHash();
- QHash<QObject *, ObjectReference>::Iterator iter =
- hash->objects.find(object);
+ QHash<QObject *, ObjectReference>::Iterator iter =
+ hash->objects.find(object);
if (iter == hash->objects.end()) {
int id = hash->nextId++;
@@ -162,7 +162,7 @@ int QDeclarativeDebugService::idForObject(QObject *object)
hash->ids.insert(id, object);
iter->object = object;
iter->id = id;
- }
+ }
return iter->id;
}
@@ -180,8 +180,8 @@ QObject *QDeclarativeDebugService::objectForId(int id)
return 0;
- QHash<QObject *, ObjectReference>::Iterator objIter =
- hash->objects.find(*iter);
+ QHash<QObject *, ObjectReference>::Iterator objIter =
+ hash->objects.find(*iter);
Q_ASSERT(objIter != hash->objects.end());
if (objIter->object == 0) {
@@ -213,8 +213,8 @@ QString QDeclarativeDebugService::objectToString(QObject *obj)
if(objectName.isEmpty())
objectName = QLatin1String("<unnamed>");
- QString rv = QString::fromUtf8(obj->metaObject()->className()) +
- QLatin1String(": ") + objectName;
+ QString rv = QString::fromUtf8(obj->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
return rv;
}
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h
index 84e63c0ddc..05580ee5c2 100644
--- a/src/declarative/debugger/qdeclarativedebugservice_p.h
+++ b/src/declarative/debugger/qdeclarativedebugservice_p.h
@@ -46,6 +46,17 @@
#include <private/qdeclarativeglobal_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.
+//
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugservice_p_p.h b/src/declarative/debugger/qdeclarativedebugservice_p_p.h
index 78076892cb..12233ed739 100644
--- a/src/declarative/debugger/qdeclarativedebugservice_p_p.h
+++ b/src/declarative/debugger/qdeclarativedebugservice_p_p.h
@@ -42,6 +42,17 @@
#ifndef QDECLARATIVEDEBUGSERVICE_P_H
#define QDECLARATIVEDEBUGSERVICE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qglobal.h>
#include <private/qobject_p.h>
diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp
index 0a46d68aa7..befc3ea374 100644
--- a/src/declarative/debugger/qdeclarativedebugtrace.cpp
+++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp
@@ -45,6 +45,8 @@
#include <QtCore/qurl.h>
#include <QtCore/qtimer.h>
+QT_BEGIN_NAMESPACE
+
Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance);
// convert to a QByteArray that can be sent to the debug client
@@ -64,8 +66,8 @@ QByteArray QDeclarativeDebugData::toByteArray() const
}
QDeclarativeDebugTrace::QDeclarativeDebugTrace()
-: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
- m_enabled(false), m_deferredSend(true), m_messageReceived(false)
+ : QDeclarativeDebugService(QLatin1String("CanvasFrameRate")),
+ m_enabled(false), m_deferredSend(true), m_messageReceived(false)
{
m_timer.start();
if (status() == Enabled) {
@@ -77,19 +79,19 @@ QDeclarativeDebugTrace::QDeclarativeDebugTrace()
void QDeclarativeDebugTrace::addEvent(EventType t)
{
- if (QDeclarativeDebugService::isDebuggingEnabled())
+ if (QDeclarativeDebugService::isDebuggingEnabled())
traceInstance()->addEventImpl(t);
}
void QDeclarativeDebugTrace::startRange(RangeType t)
{
- if (QDeclarativeDebugService::isDebuggingEnabled())
+ if (QDeclarativeDebugService::isDebuggingEnabled())
traceInstance()->startRangeImpl(t);
}
void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
{
- if (QDeclarativeDebugService::isDebuggingEnabled())
+ if (QDeclarativeDebugService::isDebuggingEnabled())
traceInstance()->rangeDataImpl(t, data);
}
@@ -113,7 +115,7 @@ void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, in
void QDeclarativeDebugTrace::endRange(RangeType t)
{
- if (QDeclarativeDebugService::isDebuggingEnabled())
+ if (QDeclarativeDebugService::isDebuggingEnabled())
traceInstance()->endRangeImpl(t);
}
@@ -223,3 +225,5 @@ void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
if (!m_enabled)
sendMessages();
}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h
index f2710cde93..fb2ef53a4a 100644
--- a/src/declarative/debugger/qdeclarativedebugtrace_p.h
+++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h
@@ -42,6 +42,17 @@
#ifndef QDECLARATIVEDEBUGTRACE_P_H
#define QDECLARATIVEDEBUGTRACE_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <private/qdeclarativedebugservice_p.h>
#include <QtCore/qelapsedtimer.h>
diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativeenginedebug.cpp
index 620ee1d66a..237e2d6376 100644
--- a/src/declarative/debugger/qdeclarativedebug.cpp
+++ b/src/declarative/debugger/qdeclarativeenginedebug.cpp
@@ -39,11 +39,11 @@
**
****************************************************************************/
-#include "private/qdeclarativedebug_p.h"
+#include "private/qdeclarativeenginedebug_p.h"
#include "private/qdeclarativedebugclient_p.h"
-#include <qdeclarativeenginedebug_p.h>
+#include <qdeclarativeenginedebugservice_p.h>
#include <private/qobject_p.h>
@@ -95,8 +95,8 @@ public:
};
QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client,
- QDeclarativeEngineDebugPrivate *p)
-: QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p)
+ QDeclarativeEngineDebugPrivate *p)
+ : QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p)
{
}
@@ -113,7 +113,7 @@ void QDeclarativeEngineDebugClient::messageReceived(const QByteArray &data)
}
QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *c)
-: client(new QDeclarativeEngineDebugClient(c, this)), nextId(0)
+ : client(new QDeclarativeEngineDebugClient(c, this)), nextId(0)
{
}
@@ -172,7 +172,7 @@ void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclara
}
void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c,
- QDeclarativeDebugRootContextQuery *q)
+ QDeclarativeDebugRootContextQuery *q)
{
if (c && q) {
QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
@@ -205,9 +205,9 @@ void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclara
}
void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugObjectReference &o,
- bool simple)
+ bool simple)
{
- QDeclarativeEngineDebugServer::QDeclarativeObjectData data;
+ QDeclarativeEngineDebugService::QDeclarativeObjectData data;
ds >> data;
o.m_debugId = data.objectId;
o.m_class = data.objectType;
@@ -234,7 +234,7 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb
ds >> propCount;
for (int ii = 0; ii < propCount; ++ii) {
- QDeclarativeEngineDebugServer::QDeclarativeObjectProperty data;
+ QDeclarativeEngineDebugService::QDeclarativeObjectProperty data;
ds >> data;
QDeclarativeDebugPropertyReference prop;
prop.m_objectDebugId = o.m_debugId;
@@ -243,22 +243,22 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb
prop.m_hasNotifySignal = data.hasNotifySignal;
prop.m_valueTypeName = data.valueTypeName;
switch (data.type) {
- case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Basic:
- case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::List:
- case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::SignalProperty:
- {
- prop.m_value = data.value;
- break;
- }
- case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Object:
- {
- QDeclarativeDebugObjectReference obj;
- obj.m_debugId = prop.m_value.toInt();
- prop.m_value = QVariant::fromValue(obj);
- break;
- }
- case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown:
- break;
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Basic:
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::List:
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::SignalProperty:
+ {
+ prop.m_value = data.value;
+ break;
+ }
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Object:
+ {
+ QDeclarativeDebugObjectReference obj;
+ obj.m_debugId = prop.m_value.toInt();
+ prop.m_value = QVariant::fromValue(obj);
+ break;
+ }
+ case QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Unknown:
+ break;
}
o.m_properties << prop;
}
@@ -332,7 +332,7 @@ void QDeclarativeEngineDebugPrivate::message(const QByteArray &data)
return;
rootContextQuery.remove(queryId);
- if (!ds.atEnd())
+ if (!ds.atEnd())
decode(ds, query->m_context);
query->m_client = 0;
@@ -411,7 +411,11 @@ void QDeclarativeEngineDebugPrivate::message(const QByteArray &data)
}
QDeclarativeEngineDebug::QDeclarativeEngineDebug(QDeclarativeDebugConnection *client, QObject *parent)
-: QObject(*(new QDeclarativeEngineDebugPrivate(client)), parent)
+ : QObject(*(new QDeclarativeEngineDebugPrivate(client)), parent)
+{
+}
+
+QDeclarativeEngineDebug::~QDeclarativeEngineDebug()
{
}
@@ -580,7 +584,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObject(const QDeclar
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
<< false << true;
d->client->sendMessage(message);
} else {
@@ -603,7 +607,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObjectRecursive(cons
QByteArray message;
QDataStream ds(&message, QIODevice::WriteOnly);
- ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
<< true << true;
d->client->sendMessage(message);
} else {
@@ -686,7 +690,7 @@ bool QDeclarativeEngineDebug::setMethodBody(int objectDebugId, const QString &me
}
QDeclarativeDebugWatch::QDeclarativeDebugWatch(QObject *parent)
-: QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1)
+ : QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1)
{
}
@@ -742,7 +746,7 @@ QString QDeclarativeDebugObjectExpressionWatch::expression() const
QDeclarativeDebugQuery::QDeclarativeDebugQuery(QObject *parent)
-: QObject(parent), m_state(Waiting)
+ : QObject(parent), m_state(Waiting)
{
}
@@ -765,13 +769,13 @@ void QDeclarativeDebugQuery::setState(State s)
}
QDeclarativeDebugEnginesQuery::QDeclarativeDebugEnginesQuery(QObject *parent)
-: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+ : QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
{
}
QDeclarativeDebugEnginesQuery::~QDeclarativeDebugEnginesQuery()
{
- if (m_client && m_queryId != -1)
+ if (m_client && m_queryId != -1)
QDeclarativeEngineDebugPrivate::remove(m_client, this);
}
@@ -781,13 +785,13 @@ QList<QDeclarativeDebugEngineReference> QDeclarativeDebugEnginesQuery::engines()
}
QDeclarativeDebugRootContextQuery::QDeclarativeDebugRootContextQuery(QObject *parent)
-: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+ : QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
{
}
QDeclarativeDebugRootContextQuery::~QDeclarativeDebugRootContextQuery()
{
- if (m_client && m_queryId != -1)
+ if (m_client && m_queryId != -1)
QDeclarativeEngineDebugPrivate::remove(m_client, this);
}
@@ -797,13 +801,13 @@ QDeclarativeDebugContextReference QDeclarativeDebugRootContextQuery::rootContext
}
QDeclarativeDebugObjectQuery::QDeclarativeDebugObjectQuery(QObject *parent)
-: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+ : QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
{
}
QDeclarativeDebugObjectQuery::~QDeclarativeDebugObjectQuery()
{
- if (m_client && m_queryId != -1)
+ if (m_client && m_queryId != -1)
QDeclarativeEngineDebugPrivate::remove(m_client, this);
}
@@ -813,13 +817,13 @@ QDeclarativeDebugObjectReference QDeclarativeDebugObjectQuery::object() const
}
QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(QObject *parent)
-: QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
+ : QDeclarativeDebugQuery(parent), m_client(0), m_queryId(-1)
{
}
QDeclarativeDebugExpressionQuery::~QDeclarativeDebugExpressionQuery()
{
- if (m_client && m_queryId != -1)
+ if (m_client && m_queryId != -1)
QDeclarativeEngineDebugPrivate::remove(m_client, this);
}
@@ -834,17 +838,17 @@ QVariant QDeclarativeDebugExpressionQuery::result() const
}
QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference()
-: m_debugId(-1)
+ : m_debugId(-1)
{
}
QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(int debugId)
-: m_debugId(debugId)
+ : m_debugId(debugId)
{
}
QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(const QDeclarativeDebugEngineReference &o)
-: m_debugId(o.m_debugId), m_name(o.m_name)
+ : m_debugId(o.m_debugId), m_name(o.m_name)
{
}
@@ -866,19 +870,19 @@ QString QDeclarativeDebugEngineReference::name() const
}
QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference()
-: m_debugId(-1), m_contextDebugId(-1)
+ : m_debugId(-1), m_contextDebugId(-1)
{
}
QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(int debugId)
-: m_debugId(debugId), m_contextDebugId(-1)
+ : m_debugId(debugId), m_contextDebugId(-1)
{
}
QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(const QDeclarativeDebugObjectReference &o)
-: m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString),
- m_name(o.m_name), m_source(o.m_source), m_contextDebugId(o.m_contextDebugId),
- m_properties(o.m_properties), m_children(o.m_children)
+ : m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString),
+ m_name(o.m_name), m_source(o.m_source), m_contextDebugId(o.m_contextDebugId),
+ m_properties(o.m_properties), m_children(o.m_children)
{
}
@@ -932,18 +936,18 @@ QList<QDeclarativeDebugObjectReference> QDeclarativeDebugObjectReference::childr
}
QDeclarativeDebugContextReference::QDeclarativeDebugContextReference()
-: m_debugId(-1)
+ : m_debugId(-1)
{
}
QDeclarativeDebugContextReference::QDeclarativeDebugContextReference(const QDeclarativeDebugContextReference &o)
-: m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
+ : m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
{
}
QDeclarativeDebugContextReference &QDeclarativeDebugContextReference::operator=(const QDeclarativeDebugContextReference &o)
{
- m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
+ m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
m_contexts = o.m_contexts;
return *this;
}
@@ -969,12 +973,12 @@ QList<QDeclarativeDebugContextReference> QDeclarativeDebugContextReference::cont
}
QDeclarativeDebugFileReference::QDeclarativeDebugFileReference()
-: m_lineNumber(-1), m_columnNumber(-1)
+ : m_lineNumber(-1), m_columnNumber(-1)
{
}
QDeclarativeDebugFileReference::QDeclarativeDebugFileReference(const QDeclarativeDebugFileReference &o)
-: m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
+ : m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
{
}
@@ -1015,14 +1019,14 @@ void QDeclarativeDebugFileReference::setColumnNumber(int c)
}
QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference()
-: m_objectDebugId(-1), m_hasNotifySignal(false)
+ : m_objectDebugId(-1), m_hasNotifySignal(false)
{
}
QDeclarativeDebugPropertyReference::QDeclarativeDebugPropertyReference(const QDeclarativeDebugPropertyReference &o)
-: m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
- m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
- m_hasNotifySignal(o.m_hasNotifySignal)
+ : m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value),
+ m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding),
+ m_hasNotifySignal(o.m_hasNotifySignal)
{
}
diff --git a/src/declarative/debugger/qdeclarativedebug_p.h b/src/declarative/debugger/qdeclarativeenginedebug_p.h
index f822637eb4..d98e4e875e 100644
--- a/src/declarative/debugger/qdeclarativedebug_p.h
+++ b/src/declarative/debugger/qdeclarativeenginedebug_p.h
@@ -38,8 +38,20 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QDECLARATIVEDEBUG_H
-#define QDECLARATIVEDEBUG_H
+
+#ifndef QDECLARATIVEENGINEDEBUG_H
+#define QDECLARATIVEENGINEDEBUG_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
@@ -69,37 +81,38 @@ class QDeclarativeDebugEngineReference;
class QDeclarativeEngineDebugPrivate;
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeEngineDebug : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
enum Status { NotConnected, Unavailable, Enabled };
explicit QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0);
+ ~QDeclarativeEngineDebug();
Status status() const;
QDeclarativeDebugPropertyWatch *addWatch(const QDeclarativeDebugPropertyReference &,
- QObject *parent = 0);
+ QObject *parent = 0);
QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugContextReference &, const QString &,
- QObject *parent = 0);
+ QObject *parent = 0);
QDeclarativeDebugObjectExpressionWatch *addWatch(const QDeclarativeDebugObjectReference &, const QString &,
- QObject *parent = 0);
+ QObject *parent = 0);
QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugObjectReference &,
- QObject *parent = 0);
+ QObject *parent = 0);
QDeclarativeDebugWatch *addWatch(const QDeclarativeDebugFileReference &,
- QObject *parent = 0);
+ QObject *parent = 0);
void removeWatch(QDeclarativeDebugWatch *watch);
QDeclarativeDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0);
QDeclarativeDebugRootContextQuery *queryRootContexts(const QDeclarativeDebugEngineReference &,
- QObject *parent = 0);
- QDeclarativeDebugObjectQuery *queryObject(const QDeclarativeDebugObjectReference &,
- QObject *parent = 0);
- QDeclarativeDebugObjectQuery *queryObjectRecursive(const QDeclarativeDebugObjectReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugObjectQuery *queryObject(const QDeclarativeDebugObjectReference &,
QObject *parent = 0);
- QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId,
- const QString &expr,
- QObject *parent = 0);
+ QDeclarativeDebugObjectQuery *queryObjectRecursive(const QDeclarativeDebugObjectReference &,
+ QObject *parent = 0);
+ QDeclarativeDebugExpressionQuery *queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ QObject *parent = 0);
bool setBindingForObject(int objectDebugId, const QString &propertyName,
const QVariant &bindingExpression, bool isLiteralValue,
QString source = QString(), int line = -1);
@@ -116,7 +129,7 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugWatch : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
enum State { Waiting, Active, Inactive, Dead };
@@ -175,15 +188,13 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugQuery : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
enum State { Waiting, Error, Completed };
State state() const;
bool isWaiting() const;
-// bool waitUntilCompleted();
-
Q_SIGNALS:
void stateChanged(QDeclarativeDebugQuery::State);
@@ -314,7 +325,7 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugEnginesQuery : public QDeclarativeDebugQuery
{
-Q_OBJECT
+ Q_OBJECT
public:
virtual ~QDeclarativeDebugEnginesQuery();
QList<QDeclarativeDebugEngineReference> engines() const;
@@ -329,7 +340,7 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugRootContextQuery : public QDeclarativeDebugQuery
{
-Q_OBJECT
+ Q_OBJECT
public:
virtual ~QDeclarativeDebugRootContextQuery();
QDeclarativeDebugContextReference rootContext() const;
@@ -344,7 +355,7 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugObjectQuery : public QDeclarativeDebugQuery
{
-Q_OBJECT
+ Q_OBJECT
public:
virtual ~QDeclarativeDebugObjectQuery();
QDeclarativeDebugObjectReference object() const;
@@ -360,7 +371,7 @@ private:
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDebugExpressionQuery : public QDeclarativeDebugQuery
{
-Q_OBJECT
+ Q_OBJECT
public:
virtual ~QDeclarativeDebugExpressionQuery();
QVariant expression() const;
@@ -384,4 +395,4 @@ Q_DECLARE_METATYPE(QDeclarativeDebugPropertyReference)
QT_END_HEADER
-#endif // QDECLARATIVEDEBUG_H
+#endif // QDECLARATIVEENGINEDEBUG_H
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
index 6c605cbc2b..9841f8778e 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "private/qdeclarativeenginedebug_p.h"
+#include "private/qdeclarativeenginedebugservice_p.h"
#include "private/qdeclarativeboundsignal_p.h"
#include "qdeclarativeengine.h"
@@ -59,23 +59,23 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer);
+Q_GLOBAL_STATIC(QDeclarativeEngineDebugService, qmlEngineDebugService);
-QDeclarativeEngineDebugServer *QDeclarativeEngineDebugServer::instance()
+QDeclarativeEngineDebugService *QDeclarativeEngineDebugService::instance()
{
- return qmlEngineDebugServer();
+ return qmlEngineDebugService();
}
-QDeclarativeEngineDebugServer::QDeclarativeEngineDebugServer(QObject *parent)
-: QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
- m_watch(new QDeclarativeWatcher(this))
+QDeclarativeEngineDebugService::QDeclarativeEngineDebugService(QObject *parent)
+ : QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
+ m_watch(new QDeclarativeWatcher(this))
{
QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
}
QDataStream &operator<<(QDataStream &ds,
- const QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
+ const QDeclarativeEngineDebugService::QDeclarativeObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
<< data.objectName << data.objectType << data.objectId << data.contextId;
@@ -83,7 +83,7 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
+ QDeclarativeEngineDebugService::QDeclarativeObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
>> data.objectName >> data.objectType >> data.objectId >> data.contextId;
@@ -91,7 +91,7 @@ QDataStream &operator>>(QDataStream &ds,
}
QDataStream &operator<<(QDataStream &ds,
- const QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
+ const QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data)
{
ds << (int)data.type << data.name << data.value << data.valueTypeName
<< data.binding << data.hasNotifySignal;
@@ -99,12 +99,12 @@ QDataStream &operator<<(QDataStream &ds,
}
QDataStream &operator>>(QDataStream &ds,
- QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
+ QDeclarativeEngineDebugService::QDeclarativeObjectProperty &data)
{
int type;
ds >> type >> data.name >> data.value >> data.valueTypeName
>> data.binding >> data.hasNotifySignal;
- data.type = (QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Type)type;
+ data.type = (QDeclarativeEngineDebugService::QDeclarativeObjectProperty::Type)type;
return ds;
}
@@ -112,7 +112,7 @@ static inline bool isSignalPropertyName(const QString &signalName)
{
// see QmlCompiler::isSignalPropertyName
return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
- signalName.at(2).isLetter() && signalName.at(2).isUpper();
+ signalName.at(2).isLetter() && signalName.at(2).isUpper();
}
static bool hasValidSignal(QObject *object, const QString &propertyName)
@@ -131,8 +131,8 @@ static bool hasValidSignal(QObject *object, const QString &propertyName)
return true;
}
-QDeclarativeEngineDebugServer::QDeclarativeObjectProperty
-QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
+QDeclarativeEngineDebugService::QDeclarativeObjectProperty
+QDeclarativeEngineDebugService::propertyData(QObject *obj, int propIdx)
{
QDeclarativeObjectProperty rv;
@@ -142,8 +142,8 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
rv.valueTypeName = QString::fromUtf8(prop.typeName());
rv.name = QString::fromUtf8(prop.name());
rv.hasNotifySignal = prop.hasNotifySignal();
- QDeclarativeAbstractBinding *binding =
- QDeclarativePropertyPrivate::binding(QDeclarativeProperty(obj, rv.name));
+ QDeclarativeAbstractBinding *binding =
+ QDeclarativePropertyPrivate::binding(QDeclarativeProperty(obj, rv.name));
if (binding)
rv.binding = binding->expression();
@@ -164,7 +164,7 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
return rv;
}
-QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const
+QVariant QDeclarativeEngineDebugService::valueContents(const QVariant &value) const
{
int userType = value.userType();
@@ -193,8 +193,8 @@ QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) con
return QLatin1String("<unknown value>");
}
-void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message,
- QObject *object, bool recur, bool dumpProperties)
+void QDeclarativeEngineDebugService::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur, bool dumpProperties)
{
message << objectData(object);
@@ -264,7 +264,7 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message,
message << fakeProperties[ii];
}
-void QDeclarativeEngineDebugServer::prepareDeferredObjects(QObject *obj)
+void QDeclarativeEngineDebugService::prepareDeferredObjects(QObject *obj)
{
qmlExecuteDeferred(obj);
@@ -276,14 +276,14 @@ void QDeclarativeEngineDebugServer::prepareDeferredObjects(QObject *obj)
}
-void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt)
+void QDeclarativeEngineDebugService::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt)
{
QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt);
QString ctxtName = ctxt->objectName();
int ctxtId = QDeclarativeDebugService::idForObject(ctxt);
- message << ctxtName << ctxtId;
+ message << ctxtName << ctxtId;
int count = 0;
@@ -316,7 +316,7 @@ void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDecla
}
}
-void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false)
+void QDeclarativeEngineDebugService::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false)
{
if (cleanList)
m_allStates.clear();
@@ -333,10 +333,10 @@ void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, b
}
}
-void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj)
+void QDeclarativeEngineDebugService::buildStatesList(QObject *obj)
{
if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) {
- m_allStates.append(state);
+ m_allStates.append(state);
}
QObjectList children = obj->children();
@@ -345,8 +345,8 @@ void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj)
}
}
-QDeclarativeEngineDebugServer::QDeclarativeObjectData
-QDeclarativeEngineDebugServer::objectData(QObject *object)
+QDeclarativeEngineDebugService::QDeclarativeObjectData
+QDeclarativeEngineDebugService::objectData(QObject *object)
{
QDeclarativeData *ddata = QDeclarativeData::get(object);
QDeclarativeObjectData rv;
@@ -385,7 +385,7 @@ QDeclarativeEngineDebugServer::objectData(QObject *object)
return rv;
}
-void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
+void QDeclarativeEngineDebugService::messageReceived(const QByteArray &message)
{
QDataStream ds(message);
@@ -416,8 +416,8 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
int engineId = -1;
ds >> queryId >> engineId;
- QDeclarativeEngine *engine =
- qobject_cast<QDeclarativeEngine *>(QDeclarativeDebugService::objectForId(engineId));
+ QDeclarativeEngine *engine =
+ qobject_cast<QDeclarativeEngine *>(QDeclarativeDebugService::objectForId(engineId));
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
@@ -545,12 +545,12 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
}
}
-void QDeclarativeEngineDebugServer::setBinding(int objectId,
- const QString &propertyName,
- const QVariant &expression,
- bool isLiteralValue,
- QString filename,
- int line)
+void QDeclarativeEngineDebugService::setBinding(int objectId,
+ const QString &propertyName,
+ const QVariant &expression,
+ bool isLiteralValue,
+ QString filename,
+ int line)
{
QObject *object = objectForId(objectId);
QDeclarativeContext *context = qmlContext(object);
@@ -600,7 +600,7 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId,
oldBinding->destroy();
binding->update();
} else {
- qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object;
+ qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
}
}
@@ -613,13 +613,13 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId,
propertyChanges->changeExpression(propertyName, expression.toString());
}
} else {
- qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object;
+ qWarning() << "QDeclarativeEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
}
}
}
}
-void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &propertyName)
+void QDeclarativeEngineDebugService::resetBinding(int objectId, const QString &propertyName)
{
QObject *object = objectForId(objectId);
QDeclarativeContext *context = qmlContext(object);
@@ -656,7 +656,7 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr
} else if (hasValidSignal(object, propertyName)) {
QDeclarativeProperty property(object, propertyName, context);
QDeclarativePropertyPrivate::setSignalExpression(property, 0);
- } else {
+ } else {
if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) {
propertyChanges->removeProperty(propertyName);
}
@@ -664,7 +664,7 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr
}
}
-void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &method, const QString &body)
+void QDeclarativeEngineDebugService::setMethodBody(int objectId, const QString &method, const QString &body)
{
QObject *object = objectForId(objectId);
QDeclarativeContext *context = qmlContext(object);
@@ -675,8 +675,8 @@ void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &m
return;
QDeclarativePropertyCache::Data dummy;
- QDeclarativePropertyCache::Data *prop =
- QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
+ QDeclarativePropertyCache::Data *prop =
+ QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
if (!prop || !prop->isVMEFunction())
return;
@@ -690,20 +690,20 @@ void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &m
paramStr.append(QString::fromUtf8(paramNames.at(ii)));
}
- QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
- QLatin1String(") {");
+ QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
+ QLatin1String(") {");
jsfunction += body;
jsfunction += QLatin1String("\n})");
- QDeclarativeVMEMetaObject *vmeMetaObject =
- static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
+ QDeclarativeVMEMetaObject *vmeMetaObject =
+ static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
vmeMetaObject->setVmeMethod(prop->coreIndex, QDeclarativeExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber));
}
-void QDeclarativeEngineDebugServer::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
+void QDeclarativeEngineDebugService::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
{
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
@@ -713,7 +713,7 @@ void QDeclarativeEngineDebugServer::propertyChanged(int id, int objectId, const
sendMessage(reply);
}
-void QDeclarativeEngineDebugServer::addEngine(QDeclarativeEngine *engine)
+void QDeclarativeEngineDebugService::addEngine(QDeclarativeEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(!m_engines.contains(engine));
@@ -721,7 +721,7 @@ void QDeclarativeEngineDebugServer::addEngine(QDeclarativeEngine *engine)
m_engines.append(engine);
}
-void QDeclarativeEngineDebugServer::remEngine(QDeclarativeEngine *engine)
+void QDeclarativeEngineDebugService::remEngine(QDeclarativeEngine *engine)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
@@ -729,7 +729,7 @@ void QDeclarativeEngineDebugServer::remEngine(QDeclarativeEngine *engine)
m_engines.removeAll(engine);
}
-void QDeclarativeEngineDebugServer::objectCreated(QDeclarativeEngine *engine, QObject *object)
+void QDeclarativeEngineDebugService::objectCreated(QDeclarativeEngine *engine, QObject *object)
{
Q_ASSERT(engine);
Q_ASSERT(m_engines.contains(engine));
diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
index 804a043635..3674b83fe7 100644
--- a/src/declarative/qml/qdeclarativeenginedebug_p.h
+++ b/src/declarative/debugger/qdeclarativeenginedebugservice_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEENGINEDEBUG_P_H
-#define QDECLARATIVEENGINEDEBUG_P_H
+#ifndef QDECLARATIVEENGINEDEBUGSERVICE_P_H
+#define QDECLARATIVEENGINEDEBUGSERVICE_P_H
//
// W A R N I N G
@@ -67,11 +67,11 @@ class QDeclarativeWatcher;
class QDataStream;
class QDeclarativeState;
-class QDeclarativeEngineDebugServer : public QDeclarativeDebugService
+class QDeclarativeEngineDebugService : public QDeclarativeDebugService
{
Q_OBJECT
public:
- QDeclarativeEngineDebugServer(QObject * = 0);
+ QDeclarativeEngineDebugService(QObject * = 0);
struct QDeclarativeObjectData {
QUrl url;
@@ -98,7 +98,7 @@ public:
void remEngine(QDeclarativeEngine *);
void objectCreated(QDeclarativeEngine *, QObject *);
- static QDeclarativeEngineDebugServer *instance();
+ static QDeclarativeEngineDebugService *instance();
protected:
virtual void messageReceived(const QByteArray &);
@@ -123,12 +123,12 @@ private:
QDeclarativeWatcher *m_watch;
QList<QWeakPointer<QDeclarativeState> > m_allStates;
};
-Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectData &);
-Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectData &);
-Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &);
-Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectData &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectData &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugService::QDeclarativeObjectProperty &);
+Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugService::QDeclarativeObjectProperty &);
QT_END_NAMESPACE
-#endif // QDECLARATIVEENGINEDEBUG_P_H
+#endif // QDECLARATIVEENGINEDEBUGSERVICE_P_H
diff --git a/src/declarative/debugger/qdeclarativeinspectorinterface_p.h b/src/declarative/debugger/qdeclarativeinspectorinterface_p.h
index aa29d6807e..d0d9f44d7b 100644
--- a/src/declarative/debugger/qdeclarativeinspectorinterface_p.h
+++ b/src/declarative/debugger/qdeclarativeinspectorinterface_p.h
@@ -39,8 +39,19 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEOBSERVERINTERFACE_H
-#define QDECLARATIVEOBSERVERINTERFACE_H
+#ifndef QDECLARATIVEINSPECTORINTERFACE_H
+#define QDECLARATIVEINSPECTORINTERFACE_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 <QtDeclarative/private/qdeclarativeglobal_p.h>
@@ -66,4 +77,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif // QDECLARATIVEOBSERVERINTERFACE_H
+#endif // QDECLARATIVEINSPECTORINTERFACE_H
diff --git a/src/declarative/debugger/qdeclarativeinspectorservice_p.h b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
index db94103210..98b2e9deeb 100644
--- a/src/declarative/debugger/qdeclarativeinspectorservice_p.h
+++ b/src/declarative/debugger/qdeclarativeinspectorservice_p.h
@@ -39,8 +39,19 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEOBSERVERSERVICE_H
-#define QDECLARATIVEOBSERVERSERVICE_H
+#ifndef QDECLARATIVEINSPECTORSERVICE_H
+#define QDECLARATIVEINSPECTORSERVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
#include "private/qdeclarativedebugservice_p.h"
#include <private/qdeclarativeglobal_p.h>
@@ -87,4 +98,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif // QDECLARATIVEOBSERVERSERVICE_H
+#endif // QDECLARATIVEINSPECTORSERVICE_H
diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp
index 9caaa79011..9b95d06e1e 100644
--- a/src/declarative/debugger/qpacketprotocol.cpp
+++ b/src/declarative/debugger/qpacketprotocol.cpp
@@ -41,12 +41,12 @@
#include "private/qpacketprotocol_p.h"
-#include <QBuffer>
-#include <QElapsedTimer>
+#include <QtCore/QBuffer>
+#include <QtCore/QElapsedTimer>
QT_BEGIN_NAMESPACE
-#define MAX_PACKET_SIZE 0x7FFFFFFF
+static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
/*!
\class QPacketProtocol
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
\brief The QPacketProtocol class encapsulates communicating discrete packets
across fragmented IO channels, such as TCP sockets.
- QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
fragmented transports such as TCP and UDP.
As transmission boundaries are not respected, sending packets over protocols
@@ -111,11 +111,11 @@ QT_BEGIN_NAMESPACE
class QPacketProtocolPrivate : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
- QPacketProtocolPrivate(QPacketProtocol * parent, QIODevice * _dev)
- : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
- waitingForPacket(false), dev(_dev)
+ QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ waitingForPacket(false), dev(_dev)
{
Q_ASSERT(4 == sizeof(qint32));
@@ -150,8 +150,8 @@ public Q_SLOTS:
{
Q_ASSERT(!sendingPackets.isEmpty());
- while(bytes) {
- if(sendingPackets.at(0) > bytes) {
+ while (bytes) {
+ if (sendingPackets.at(0) > bytes) {
sendingPackets[0] -= bytes;
bytes = 0;
} else {
@@ -214,15 +214,15 @@ public:
qint32 inProgressSize;
qint32 maxPacketSize;
bool waitingForPacket;
- QIODevice * dev;
+ QIODevice *dev;
};
/*!
Construct a QPacketProtocol instance that works on \a dev with the
specified \a parent.
*/
-QPacketProtocol::QPacketProtocol(QIODevice * dev, QObject * parent)
-: QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
+ : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
{
Q_ASSERT(dev);
}
@@ -236,7 +236,7 @@ QPacketProtocol::~QPacketProtocol()
/*!
Returns the maximum packet size allowed. By default this is
- 2,147,483,647 bytes.
+ 2,147,483,647 bytes.
If a packet claiming to be larger than the maximum packet size is received,
the QPacketProtocol::invalidPacket() signal is emitted.
@@ -255,7 +255,7 @@ qint32 QPacketProtocol::maximumPacketSize() const
*/
qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
{
- if(max > (signed)sizeof(qint32))
+ if (max > (signed)sizeof(qint32))
d->maxPacketSize = max;
return d->maxPacketSize;
}
@@ -267,7 +267,7 @@ qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
protocol.send() << "Hello world" << 123;
\endcode
- will send a packet containing "Hello world" and 123. To construct more
+ will send a packet containing "Hello world" and 123. To construct more
complex packets, explicitly construct a QPacket instance.
*/
QPacketAutoSend QPacketProtocol::send()
@@ -282,7 +282,7 @@ QPacketAutoSend QPacketProtocol::send()
*/
void QPacketProtocol::send(const QPacket & p)
{
- if(p.b.isEmpty())
+ if (p.b.isEmpty())
return; // We don't send empty packets
qint64 sendSize = p.b.size() + sizeof(qint32);
@@ -317,7 +317,7 @@ void QPacketProtocol::clear()
*/
QPacket QPacketProtocol::read()
{
- if(0 == d->packets.count())
+ if (0 == d->packets.count())
return QPacket();
QPacket rv(d->packets.at(0));
@@ -370,7 +370,7 @@ bool QPacketProtocol::waitForReadyRead(int msecs)
/*!
Return the QIODevice passed to the QPacketProtocol constructor.
*/
-QIODevice * QPacketProtocol::device()
+QIODevice *QPacketProtocol::device()
{
return d->dev;
}
@@ -433,8 +433,8 @@ QIODevice * QPacketProtocol::device()
\endcode
Only packets returned from QPacketProtocol::read() may be read from. QPacket
- instances constructed by directly by applications are for transmission only
- and are considered "write only". Attempting to read data from them will
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
result in undefined behavior.
\ingroup io
@@ -445,7 +445,7 @@ QIODevice * QPacketProtocol::device()
Constructs an empty write-only packet.
*/
QPacket::QPacket()
-: QDataStream(), buf(0)
+ : QDataStream(), buf(0)
{
buf = new QBuffer(&b);
buf->open(QIODevice::WriteOnly);
@@ -458,7 +458,7 @@ QPacket::QPacket()
*/
QPacket::~QPacket()
{
- if(buf) {
+ if (buf) {
delete buf;
buf = 0;
}
@@ -469,7 +469,7 @@ QPacket::~QPacket()
two packets are otherwise independent.
*/
QPacket::QPacket(const QPacket & other)
-: QDataStream(), b(other.b), buf(0)
+ : QDataStream(), b(other.b), buf(0)
{
buf = new QBuffer(&b);
buf->open(other.buf->openMode());
@@ -480,7 +480,7 @@ QPacket::QPacket(const QPacket & other)
\internal
*/
QPacket::QPacket(const QByteArray & ba)
-: QDataStream(), b(ba), buf(0)
+ : QDataStream(), b(ba), buf(0)
{
buf = new QBuffer(&b);
buf->open(QIODevice::ReadOnly);
@@ -534,14 +534,14 @@ void QPacket::clear()
\internal
*/
-QPacketAutoSend::QPacketAutoSend(QPacketProtocol * _p)
-: QPacket(), p(_p)
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
+ : QPacket(), p(_p)
{
}
QPacketAutoSend::~QPacketAutoSend()
{
- if(!b.isEmpty())
+ if (!b.isEmpty())
p->send(*this);
}
diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h
index df3b170d17..5d9d820317 100644
--- a/src/declarative/debugger/qpacketprotocol_p.h
+++ b/src/declarative/debugger/qpacketprotocol_p.h
@@ -42,6 +42,17 @@
#ifndef QPACKETPROTOCOL_H
#define QPACKETPROTOCOL_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qobject.h>
#include <QtCore/qdatastream.h>
@@ -61,9 +72,9 @@ class QPacketProtocolPrivate;
class Q_DECLARATIVE_PRIVATE_EXPORT QPacketProtocol : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
- explicit QPacketProtocol(QIODevice * dev, QObject * parent = 0);
+ explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
virtual ~QPacketProtocol();
qint32 maximumPacketSize() const;
@@ -79,7 +90,7 @@ public:
void clear();
- QIODevice * device();
+ QIODevice *device();
Q_SIGNALS:
void readyRead();
@@ -87,7 +98,7 @@ Q_SIGNALS:
void packetWritten();
private:
- QPacketProtocolPrivate * d;
+ QPacketProtocolPrivate *d;
};
@@ -104,9 +115,9 @@ public:
protected:
friend class QPacketProtocol;
- QPacket(const QByteArray & ba);
+ QPacket(const QByteArray &ba);
QByteArray b;
- QBuffer * buf;
+ QBuffer *buf;
};
class Q_DECLARATIVE_PRIVATE_EXPORT QPacketAutoSend : public QPacket
@@ -117,7 +128,7 @@ public:
private:
friend class QPacketProtocol;
QPacketAutoSend(QPacketProtocol *);
- QPacketProtocol * p;
+ QPacketProtocol *p;
};
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qv8debugservice.cpp b/src/declarative/debugger/qv8debugservice.cpp
index 7d3f45e35e..7729e5bdf6 100644
--- a/src/declarative/debugger/qv8debugservice.cpp
+++ b/src/declarative/debugger/qv8debugservice.cpp
@@ -56,7 +56,9 @@ Q_GLOBAL_STATIC(QV8DebugService, v8ServiceInstance)
void DebugMessageHandler(const v8::Debug::Message& message)
{
v8::DebugEvent event = message.GetEvent();
- if (event != v8::Break && event != v8::Exception && event != v8::AfterCompile) {
+
+ if (event != v8::Break && event != v8::Exception &&
+ event != v8::AfterCompile && event != v8::BeforeCompile) {
return;
}
@@ -65,7 +67,8 @@ void DebugMessageHandler(const v8::Debug::Message& message)
QV8DebugService *service = QV8DebugService::instance();
service->debugMessageHandler(response);
- if (event == v8::Break && !message.WillStartRunning()) {
+ if ((event == v8::Break || event == v8::Exception) &&
+ !message.WillStartRunning()) {
service->executionStopped();
} else if (event == v8::AfterCompile) {
service->appendSourcePath(response);
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index 4e5ff4c17d..3cf0d39d58 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -33,6 +33,7 @@ include(debugger/debugger.pri)
include(scenegraph/scenegraph.pri)
include(items/items.pri)
include(particles/particles.pri)
+include(designer/designer.pri)
symbian: {
TARGET.UID3=0x2001E623
diff --git a/src/declarative/designer/designer.pri b/src/declarative/designer/designer.pri
new file mode 100644
index 0000000000..c523525977
--- /dev/null
+++ b/src/declarative/designer/designer.pri
@@ -0,0 +1,2 @@
+HEADERS += designer/designersupport.h
+SOURCES += designer/designersupport.cpp
diff --git a/src/declarative/designer/designersupport.cpp b/src/declarative/designer/designersupport.cpp
new file mode 100644
index 0000000000..aaaeeb4ef0
--- /dev/null
+++ b/src/declarative/designer/designersupport.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "designersupport.h"
+#include "qsgitem_p.h"
+
+#include <QtDeclarative/private/qsgshadereffectsource_p.h>
+#include <QtDeclarative/private/qsgrectangle_p.h>
+#include <QtDeclarative/private/qdeclarativeengine_p.h>
+#include <QtDeclarative/private/qsgview_p.h>
+#include <QtDeclarative/private/qdeclarativestategroup_p.h>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+DesignerSupport::DesignerSupport()
+{
+}
+
+DesignerSupport::~DesignerSupport()
+{
+ QHash<QSGItem*, QSGShaderEffectTexture*>::iterator iterator;
+
+ for (iterator = m_itemTextureHash.begin(); iterator != m_itemTextureHash.end(); ++iterator) {
+ QSGShaderEffectTexture *texture = iterator.value();
+ QSGItem *item = iterator.key();
+ QSGItemPrivate::get(item)->derefFromEffectItem(true);
+ delete texture;
+ }
+}
+
+void DesignerSupport::refFromEffectItem(QSGItem *referencedItem, bool hide)
+{
+ if (referencedItem == 0)
+ return;
+
+ QSGItemPrivate::get(referencedItem)->refFromEffectItem(hide);
+ QSGCanvasPrivate::get(referencedItem->canvas())->updateDirtyNode(referencedItem);
+
+ Q_ASSERT(QSGItemPrivate::get(referencedItem)->rootNode);
+
+ if (!m_itemTextureHash.contains(referencedItem)) {
+ QSGShaderEffectTexture *texture = new QSGShaderEffectTexture(referencedItem);
+
+ texture->setLive(true);
+ texture->setItem(QSGItemPrivate::get(referencedItem)->rootNode);
+ texture->setRect(referencedItem->boundingRect());
+ texture->setSize(referencedItem->boundingRect().size().toSize());
+ texture->setRecursive(true);
+#ifndef QT_OPENGL_ES
+ texture->setFormat(GL_RGBA8);
+#else
+ texture->setFormat(GL_RGBA);
+#endif
+ texture->setHasMipmaps(false);
+
+ m_itemTextureHash.insert(referencedItem, texture);
+ }
+}
+
+void DesignerSupport::derefFromEffectItem(QSGItem *referencedItem, bool unhide)
+{
+ if (referencedItem == 0)
+ return;
+
+ delete m_itemTextureHash.take(referencedItem);
+ QSGItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
+}
+
+QImage DesignerSupport::renderImageForItem(QSGItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
+{
+ if (referencedItem == 0 || referencedItem->parentItem() == 0) {
+ qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
+ return QImage();
+ }
+
+ QSGShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
+
+ Q_ASSERT(renderTexture);
+ if (renderTexture == 0)
+ return QImage();
+ renderTexture->setRect(boundingRect);
+ renderTexture->setSize(imageSize);
+ renderTexture->updateTexture();
+
+ QImage renderImage = renderTexture->toImage();
+ renderImage = renderImage.mirrored(false, true);
+
+ if (renderImage.size().isEmpty())
+ qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
+
+ return renderImage;
+}
+
+bool DesignerSupport::isDirty(QSGItem *referencedItem, DirtyType dirtyType)
+{
+ if (referencedItem == 0)
+ return false;
+
+ return QSGItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
+}
+
+void DesignerSupport::resetDirty(QSGItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return;
+
+ QSGItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
+ QSGItemPrivate::get(referencedItem)->removeFromDirtyList();
+}
+
+QTransform DesignerSupport::canvasTransform(QSGItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return QTransform();
+
+ return QSGItemPrivate::get(referencedItem)->itemToCanvasTransform();
+}
+
+QTransform DesignerSupport::parentTransform(QSGItem *referencedItem)
+{
+ if (referencedItem == 0)
+ return QTransform();
+
+ QTransform parentTransform;
+
+ QSGItemPrivate::get(referencedItem)->itemToParentTransform(parentTransform);
+
+ return parentTransform;
+}
+
+QString propertyNameForAnchorLine(const QSGAnchorLine::AnchorLine &anchorLine)
+{
+ switch (anchorLine) {
+ case QSGAnchorLine::Left: return QLatin1String("left");
+ case QSGAnchorLine::Right: return QLatin1String("right");
+ case QSGAnchorLine::Top: return QLatin1String("top");
+ case QSGAnchorLine::Bottom: return QLatin1String("bottom");
+ case QSGAnchorLine::HCenter: return QLatin1String("horizontalCenter");
+ case QSGAnchorLine::VCenter: return QLatin1String("verticalCenter");
+ case QSGAnchorLine::Baseline: return QLatin1String("baseline");
+ case QSGAnchorLine::Invalid:
+ default: return QString();
+ }
+}
+
+bool isValidAnchorName(const QString &name)
+{
+ static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
+ << QLatin1String("anchors.left")
+ << QLatin1String("anchors.right")
+ << QLatin1String("anchors.bottom")
+ << QLatin1String("anchors.verticalCenter")
+ << QLatin1String("anchors.horizontalCenter")
+ << QLatin1String("anchors.fill")
+ << QLatin1String("anchors.centerIn")
+ << QLatin1String("anchors.baseline"));
+
+ return anchorNameList.contains(name);
+}
+
+bool DesignerSupport::isAnchoredTo(QSGItem *fromItem, QSGItem *toItem)
+{
+ Q_ASSERT(dynamic_cast<QSGItemPrivate*>(QSGItemPrivate::get(fromItem)));
+ QSGItemPrivate *fromItemPrivate = static_cast<QSGItemPrivate*>(QSGItemPrivate::get(fromItem));
+ QSGAnchors *anchors = fromItemPrivate->anchors();
+ return anchors->fill() == toItem
+ || anchors->centerIn() == toItem
+ || anchors->bottom().item == toItem
+ || anchors->top().item == toItem
+ || anchors->left().item == toItem
+ || anchors->right().item == toItem
+ || anchors->verticalCenter().item == toItem
+ || anchors->horizontalCenter().item == toItem
+ || anchors->baseline().item == toItem;
+}
+
+bool DesignerSupport::areChildrenAnchoredTo(QSGItem *fromItem, QSGItem *toItem)
+{
+ foreach (QSGItem *childItem, fromItem->childItems()) {
+ if (childItem) {
+ if (isAnchoredTo(childItem, toItem))
+ return true;
+
+ if (areChildrenAnchoredTo(childItem, toItem))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QSGAnchors *anchors(QSGItem *item)
+{
+ QSGItemPrivate *itemPrivate = static_cast<QSGItemPrivate*>(QSGItemPrivate::get(item));
+ return itemPrivate->anchors();
+}
+
+QSGAnchors::Anchor anchorLineFlagForName(const QString &name)
+{
+ if (name == QLatin1String("anchors.top"))
+ return QSGAnchors::TopAnchor;
+
+ if (name == QLatin1String("anchors.left"))
+ return QSGAnchors::LeftAnchor;
+
+ if (name == QLatin1String("anchors.bottom"))
+ return QSGAnchors::BottomAnchor;
+
+ if (name == QLatin1String("anchors.right"))
+ return QSGAnchors::RightAnchor;
+
+ if (name == QLatin1String("anchors.horizontalCenter"))
+ return QSGAnchors::HCenterAnchor;
+
+ if (name == QLatin1String("anchors.verticalCenter"))
+ return QSGAnchors::VCenterAnchor;
+
+ if (name == QLatin1String("anchors.baseline"))
+ return QSGAnchors::BaselineAnchor;
+
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
+ return QSGAnchors::LeftAnchor;
+}
+
+bool DesignerSupport::hasAnchor(QSGItem *item, const QString &name)
+{
+ if (!isValidAnchorName(name))
+ return false;
+
+ if (name == QLatin1String("anchors.fill"))
+ return anchors(item)->fill() != 0;
+
+ if (name == QLatin1String("anchors.centerIn"))
+ return anchors(item)->centerIn() != 0;
+
+ if (name == QLatin1String("anchors.right"))
+ return anchors(item)->right().item != 0;
+
+ if (name == QLatin1String("anchors.top"))
+ return anchors(item)->top().item != 0;
+
+ if (name == QLatin1String("anchors.left"))
+ return anchors(item)->left().item != 0;
+
+ if (name == QLatin1String("anchors.bottom"))
+ return anchors(item)->bottom().item != 0;
+
+ if (name == QLatin1String("anchors.horizontalCenter"))
+ return anchors(item)->horizontalCenter().item != 0;
+
+ if (name == QLatin1String("anchors.verticalCenter"))
+ return anchors(item)->verticalCenter().item != 0;
+
+ if (name == QLatin1String("anchors.baseline"))
+ return anchors(item)->baseline().item != 0;
+
+ return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
+}
+
+QSGItem *DesignerSupport::anchorFillTargetItem(QSGItem *item)
+{
+ return anchors(item)->fill();
+}
+
+QSGItem *DesignerSupport::anchorCenterInTargetItem(QSGItem *item)
+{
+ return anchors(item)->centerIn();
+}
+
+
+
+QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QSGItem *item, const QString &name, QDeclarativeContext *context)
+{
+ QObject *targetObject = 0;
+ QString targetName;
+
+ if (name == QLatin1String("anchors.fill")) {
+ targetObject = anchors(item)->fill();
+ } else if (name == QLatin1String("anchors.centerIn")) {
+ targetObject = anchors(item)->centerIn();
+ } else {
+ QDeclarativeProperty metaProperty(item, name, context);
+ if (!metaProperty.isValid())
+ return QPair<QString, QObject*>();
+
+ QSGAnchorLine anchorLine = metaProperty.read().value<QSGAnchorLine>();
+ if (anchorLine.anchorLine != QSGAnchorLine::Invalid) {
+ targetObject = anchorLine.item;
+ targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
+ }
+
+ }
+
+ return QPair<QString, QObject*>(targetName, targetObject);
+}
+
+void DesignerSupport::resetAnchor(QSGItem *item, const QString &name)
+{
+ if (name == QLatin1String("anchors.fill")) {
+ anchors(item)->resetFill();
+ } else if (name == QLatin1String("anchors.centerIn")) {
+ anchors(item)->resetCenterIn();
+ } else if (name == QLatin1String("anchors.top")) {
+ anchors(item)->resetTop();
+ } else if (name == QLatin1String("anchors.left")) {
+ anchors(item)->resetLeft();
+ } else if (name == QLatin1String("anchors.right")) {
+ anchors(item)->resetRight();
+ } else if (name == QLatin1String("anchors.bottom")) {
+ anchors(item)->resetBottom();
+ } else if (name == QLatin1String("anchors.horizontalCenter")) {
+ anchors(item)->resetHorizontalCenter();
+ } else if (name == QLatin1String("anchors.verticalCenter")) {
+ anchors(item)->resetVerticalCenter();
+ } else if (name == QLatin1String("anchors.baseline")) {
+ anchors(item)->resetBaseline();
+ }
+}
+
+QList<QObject*> DesignerSupport::statesForItem(QSGItem *item)
+{
+ QList<QObject*> objectList;
+ QList<QDeclarativeState *> stateList = QSGItemPrivate::get(item)->_states()->states();
+ qCopy(stateList.begin(), stateList.end(), objectList.begin());
+
+ return objectList;
+}
+
+bool DesignerSupport::isComponentComplete(QSGItem *item)
+{
+ return static_cast<QSGItemPrivate*>(QSGItemPrivate::get(item))->componentComplete;
+}
+
+int DesignerSupport::borderWidth(QSGItem *item)
+{
+ QSGRectangle *rectangle = qobject_cast<QSGRectangle*>(item);
+ if (rectangle)
+ return rectangle->border()->width();
+
+ return 0;
+}
+
+void DesignerSupport::refreshExpressions(QDeclarativeContext *context)
+{
+ QDeclarativeContextPrivate::get(context)->data->refreshExpressions();
+}
+
+void DesignerSupport::setRootItem(QSGView *view, QSGItem *item)
+{
+ QSGViewPrivate::get(view)->setRootObject(item);
+}
+
+bool DesignerSupport::isValidWidth(QSGItem *item)
+{
+ return QSGItemPrivate::get(item)->heightValid;
+}
+
+bool DesignerSupport::isValidHeight(QSGItem *item)
+{
+ return QSGItemPrivate::get(item)->widthValid;
+}
+
+void DesignerSupport::updateDirtyNode(QSGItem *item)
+{
+ QSGCanvasPrivate::get(item->canvas())->updateDirtyNode(item);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/designer/designersupport.h b/src/declarative/designer/designersupport.h
new file mode 100644
index 0000000000..b52a4a23d3
--- /dev/null
+++ b/src/declarative/designer/designersupport.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 DESIGNERSUPPORT_H
+#define DESIGNERSUPPORT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QHash>
+#include <QtCore/QRectF>
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QSGItem;
+class QSGShaderEffectTexture;
+class QImage;
+class QTransform;
+class QDeclarativeContext;
+class QSGView;
+
+
+class Q_DECLARATIVE_EXPORT DesignerSupport
+{
+public:
+ enum DirtyType {
+ TransformOrigin = 0x00000001,
+ Transform = 0x00000002,
+ BasicTransform = 0x00000004,
+ Position = 0x00000008,
+ Size = 0x00000010,
+
+ ZValue = 0x00000020,
+ Content = 0x00000040,
+ Smooth = 0x00000080,
+ OpacityValue = 0x00000100,
+ ChildrenChanged = 0x00000200,
+ ChildrenStackingChanged = 0x00000400,
+ ParentChanged = 0x00000800,
+
+ Clip = 0x00001000,
+ Canvas = 0x00002000,
+
+ EffectReference = 0x00008000,
+ Visible = 0x00010000,
+ HideReference = 0x00020000,
+
+ TransformUpdateMask = TransformOrigin | Transform | BasicTransform | Position | Size | Canvas,
+ ComplexTransformUpdateMask = Transform | Canvas,
+ ContentUpdateMask = Size | Content | Smooth | Canvas,
+ ChildrenUpdateMask = ChildrenChanged | ChildrenStackingChanged | EffectReference | Canvas
+ };
+
+
+ DesignerSupport();
+ ~DesignerSupport();
+
+ void refFromEffectItem(QSGItem *referencedItem, bool hide = true);
+ void derefFromEffectItem(QSGItem *referencedItem, bool unhide = true);
+
+ QImage renderImageForItem(QSGItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize);
+
+ static bool isDirty(QSGItem *referencedItem, DirtyType dirtyType);
+ static void resetDirty(QSGItem *referencedItem);
+
+ static QTransform canvasTransform(QSGItem *referencedItem);
+ static QTransform parentTransform(QSGItem *referencedItem);
+
+ static bool isAnchoredTo(QSGItem *fromItem, QSGItem *toItem);
+ static bool areChildrenAnchoredTo(QSGItem *fromItem, QSGItem *toItem);
+ static bool hasAnchor(QSGItem *item, const QString &name);
+ static QSGItem *anchorFillTargetItem(QSGItem *item);
+ static QSGItem *anchorCenterInTargetItem(QSGItem *item);
+ static QPair<QString, QObject*> anchorLineTarget(QSGItem *item, const QString &name, QDeclarativeContext *context);
+ static void resetAnchor(QSGItem *item, const QString &name);
+
+
+ static QList<QObject*> statesForItem(QSGItem *item);
+
+ static bool isComponentComplete(QSGItem *item);
+
+ static int borderWidth(QSGItem *item);
+
+ static void refreshExpressions(QDeclarativeContext *context);
+
+ static void setRootItem(QSGView *view, QSGItem *item);
+
+ static bool isValidWidth(QSGItem *item);
+ static bool isValidHeight(QSGItem *item);
+
+ static void updateDirtyNode(QSGItem *item);
+
+private:
+ QHash<QSGItem*, QSGShaderEffectTexture*> m_itemTextureHash;
+};
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERSUPPORT_H
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp
index 7a8465a4bc..e5f2eca6b1 100644
--- a/src/declarative/items/context2d/qsgcontext2d.cpp
+++ b/src/declarative/items/context2d/qsgcontext2d.cpp
@@ -46,6 +46,7 @@
#include <QtGui/qopenglframebufferobject.h>
#include <QtCore/qdebug.h>
#include "private/qsgcontext_p.h"
+#include "private/qdeclarativesvgparser_p.h"
#include <QtGui/qguiapplication.h>
#include <qdeclarativeinfo.h>
@@ -77,6 +78,7 @@ void copy_vector(QVector<T>* dst, const QVector<T>& src)
}
static bool parsePathDataFast(const QString &dataStr, QPainterPath &path);
+
#define DEGREES(t) ((t) * 180.0 / Q_PI)
#define qClamp(val, min, max) qMin(qMax(val, min), max)
@@ -2310,7 +2312,7 @@ void QSGContext2D::setPath(QSGCanvasPath* path)
QSGCanvasPath* QSGContext2D::createPath(const QString& pathString)
{
QPainterPath path;
- if (parsePathDataFast(pathString, path)) {
+ if (QDeclarativeSvgParser::parsePathDataFast(pathString, path)) {
return new QSGCanvasPath(path, this);
}
return 0;
@@ -2571,592 +2573,11 @@ bool QSGContext2D::isPointInPath(qreal x, qreal y) const
return d->path.contains(QPointF(x, y));
}
-//copied from QtSvg (qsvghandler.cpp).
-Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-// '0' is 0x30 and '9' is 0x39
-static inline bool isDigit(ushort ch)
-{
- static quint16 magic = 0x3ff;
- return ((ch >> 4) == 3) && (magic >> (ch & 15));
-}
-
-static qreal toDouble(const QChar *&str)
-{
- const int maxLen = 255;//technically doubles can go til 308+ but whatever
- char temp[maxLen+1];
- int pos = 0;
-
- if (*str == QLatin1Char('-')) {
- temp[pos++] = '-';
- ++str;
- } else if (*str == QLatin1Char('+')) {
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- if (*str == QLatin1Char('.') && pos < maxLen) {
- temp[pos++] = '.';
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- bool exponent = false;
- if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
- exponent = true;
- temp[pos++] = 'e';
- ++str;
- if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- }
-
- temp[pos] = '\0';
-
- qreal val;
- if (!exponent && pos < 10) {
- int ival = 0;
- const char *t = temp;
- bool neg = false;
- if(*t == '-') {
- neg = true;
- ++t;
- }
- while(*t && *t != '.') {
- ival *= 10;
- ival += (*t) - '0';
- ++t;
- }
- if(*t == '.') {
- ++t;
- int div = 1;
- while(*t) {
- ival *= 10;
- ival += (*t) - '0';
- div *= 10;
- ++t;
- }
- val = ((qreal)ival)/((qreal)div);
- } else {
- val = ival;
- }
- if (neg)
- val = -val;
- } else {
-#if defined(Q_WS_QWS) && !defined(Q_OS_VXWORKS)
- if(sizeof(qreal) == sizeof(float))
- val = strtof(temp, 0);
- else
-#endif
- {
- bool ok = false;
- val = qstrtod(temp, 0, &ok);
- }
- }
- return val;
-
-}
-static qreal toDouble(const QString &str, bool *ok = NULL)
-{
- const QChar *c = str.constData();
- qreal res = toDouble(c);
- if (ok) {
- *ok = ((*c) == QLatin1Char('\0'));
- }
- return res;
-}
-
-static qreal toDouble(const QStringRef &str, bool *ok = NULL)
-{
- const QChar *c = str.constData();
- qreal res = toDouble(c);
- if (ok) {
- *ok = (c == (str.constData() + str.length()));
- }
- return res;
-}
-static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
-{
- while (str->isSpace())
- ++str;
- while (isDigit(str->unicode()) ||
- *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
- *str == QLatin1Char('.')) {
-
- points.append(toDouble(str));
-
- while (str->isSpace())
- ++str;
- if (*str == QLatin1Char(','))
- ++str;
-
- //eat the rest of space
- while (str->isSpace())
- ++str;
- }
-}
-
-static void pathArcSegment(QPainterPath &path,
- qreal xc, qreal yc,
- qreal th0, qreal th1,
- qreal rx, qreal ry, qreal xAxisRotation)
-{
- qreal sinTh, cosTh;
- qreal a00, a01, a10, a11;
- qreal x1, y1, x2, y2, x3, y3;
- qreal t;
- qreal thHalf;
-
- sinTh = qSin(xAxisRotation * (Q_PI / 180.0));
- cosTh = qCos(xAxisRotation * (Q_PI / 180.0));
-
- a00 = cosTh * rx;
- a01 = -sinTh * ry;
- a10 = sinTh * rx;
- a11 = cosTh * ry;
-
- thHalf = 0.5 * (th1 - th0);
- t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
- x1 = xc + qCos(th0) - t * qSin(th0);
- y1 = yc + qSin(th0) + t * qCos(th0);
- x3 = xc + qCos(th1);
- y3 = yc + qSin(th1);
- x2 = x3 + t * qSin(th1);
- y2 = y3 - t * qCos(th1);
-
- path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
- a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
- a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
-}
-
-static void pathArc(QPainterPath &path,
- qreal rx,
- qreal ry,
- qreal x_axis_rotation,
- int large_arc_flag,
- int sweep_flag,
- qreal x,
- qreal y,
- qreal curx, qreal cury)
-{
- qreal sin_th, cos_th;
- qreal a00, a01, a10, a11;
- qreal x0, y0, x1, y1, xc, yc;
- qreal d, sfactor, sfactor_sq;
- qreal th0, th1, th_arc;
- int i, n_segs;
- qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
-
- rx = qAbs(rx);
- ry = qAbs(ry);
-
- sin_th = qSin(x_axis_rotation * (Q_PI / 180.0));
- cos_th = qCos(x_axis_rotation * (Q_PI / 180.0));
-
- dx = (curx - x) / 2.0;
- dy = (cury - y) / 2.0;
- dx1 = cos_th * dx + sin_th * dy;
- dy1 = -sin_th * dx + cos_th * dy;
- Pr1 = rx * rx;
- Pr2 = ry * ry;
- Px = dx1 * dx1;
- Py = dy1 * dy1;
- /* Spec : check if radii are large enough */
- check = Px / Pr1 + Py / Pr2;
- if (check > 1) {
- rx = rx * qSqrt(check);
- ry = ry * qSqrt(check);
- }
-
- a00 = cos_th / rx;
- a01 = sin_th / rx;
- a10 = -sin_th / ry;
- a11 = cos_th / ry;
- x0 = a00 * curx + a01 * cury;
- y0 = a10 * curx + a11 * cury;
- x1 = a00 * x + a01 * y;
- y1 = a10 * x + a11 * y;
- /* (x0, y0) is current point in transformed coordinate space.
- (x1, y1) is new point in transformed coordinate space.
-
- The arc fits a unit-radius circle in this space.
- */
- d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
- sfactor_sq = 1.0 / d - 0.25;
- if (sfactor_sq < 0) sfactor_sq = 0;
- sfactor = qSqrt(sfactor_sq);
- if (sweep_flag == large_arc_flag) sfactor = -sfactor;
- xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
- yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
- /* (xc, yc) is center of the circle. */
-
- th0 = qAtan2(y0 - yc, x0 - xc);
- th1 = qAtan2(y1 - yc, x1 - xc);
-
- th_arc = th1 - th0;
- if (th_arc < 0 && sweep_flag)
- th_arc += 2 * Q_PI;
- else if (th_arc > 0 && !sweep_flag)
- th_arc -= 2 * Q_PI;
-
- n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
-
- for (i = 0; i < n_segs; i++) {
- pathArcSegment(path, xc, yc,
- th0 + i * th_arc / n_segs,
- th0 + (i + 1) * th_arc / n_segs,
- rx, ry, x_axis_rotation);
- }
-}
-
-
-static bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
-{
- qreal x0 = 0, y0 = 0; // starting point
- qreal x = 0, y = 0; // current point
- char lastMode = 0;
- QPointF ctrlPt;
- const QChar *str = dataStr.constData();
- const QChar *end = str + dataStr.size();
-
- while (str != end) {
- while (str->isSpace())
- ++str;
- QChar pathElem = *str;
- ++str;
- QChar endc = *end;
- *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
- QVarLengthArray<qreal, 8> arg;
- parseNumbersArray(str, arg);
- *const_cast<QChar *>(end) = endc;
- if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
- arg.append(0);//dummy
- const qreal *num = arg.constData();
- int count = arg.count();
- while (count > 0) {
- qreal offsetX = x; // correction offsets
- qreal offsetY = y; // for relative commands
- switch (pathElem.unicode()) {
- case 'm': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = x0 = num[0] + offsetX;
- y = y0 = num[1] + offsetY;
- num += 2;
- count -= 2;
- path.moveTo(x0, y0);
-
- // As per 1.2 spec 8.3.2 The "moveto" commands
- // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
- // the subsequent pairs shall be treated as implicit 'lineto' commands.
- pathElem = QLatin1Char('l');
- }
- break;
- case 'M': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = x0 = num[0];
- y = y0 = num[1];
- num += 2;
- count -= 2;
- path.moveTo(x0, y0);
-
- // As per 1.2 spec 8.3.2 The "moveto" commands
- // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
- // the subsequent pairs shall be treated as implicit 'lineto' commands.
- pathElem = QLatin1Char('L');
- }
- break;
- case 'z':
- case 'Z': {
- x = x0;
- y = y0;
- count--; // skip dummy
- num++;
- path.closeSubpath();
- }
- break;
- case 'l': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = num[0] + offsetX;
- y = num[1] + offsetY;
- num += 2;
- count -= 2;
- path.lineTo(x, y);
-
- }
- break;
- case 'L': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = num[0];
- y = num[1];
- num += 2;
- count -= 2;
- path.lineTo(x, y);
- }
- break;
- case 'h': {
- x = num[0] + offsetX;
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'H': {
- x = num[0];
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'v': {
- y = num[0] + offsetY;
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'V': {
- y = num[0];
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'c': {
- if (count < 6) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1(num[0] + offsetX, num[1] + offsetY);
- QPointF c2(num[2] + offsetX, num[3] + offsetY);
- QPointF e(num[4] + offsetX, num[5] + offsetY);
- num += 6;
- count -= 6;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'C': {
- if (count < 6) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1(num[0], num[1]);
- QPointF c2(num[2], num[3]);
- QPointF e(num[4], num[5]);
- num += 6;
- count -= 6;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 's': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1;
- if (lastMode == 'c' || lastMode == 'C' ||
- lastMode == 's' || lastMode == 'S')
- c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c1 = QPointF(x, y);
- QPointF c2(num[0] + offsetX, num[1] + offsetY);
- QPointF e(num[2] + offsetX, num[3] + offsetY);
- num += 4;
- count -= 4;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'S': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1;
- if (lastMode == 'c' || lastMode == 'C' ||
- lastMode == 's' || lastMode == 'S')
- c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c1 = QPointF(x, y);
- QPointF c2(num[0], num[1]);
- QPointF e(num[2], num[3]);
- num += 4;
- count -= 4;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'q': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c(num[0] + offsetX, num[1] + offsetY);
- QPointF e(num[2] + offsetX, num[3] + offsetY);
- num += 4;
- count -= 4;
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'Q': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c(num[0], num[1]);
- QPointF e(num[2], num[3]);
- num += 4;
- count -= 4;
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 't': {
- if (count < 2) {
- num += count;
- count = 0;
- break;
- }
- QPointF e(num[0] + offsetX, num[1] + offsetY);
- num += 2;
- count -= 2;
- QPointF c;
- if (lastMode == 'q' || lastMode == 'Q' ||
- lastMode == 't' || lastMode == 'T')
- c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c = QPointF(x, y);
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'T': {
- if (count < 2) {
- num += count;
- count = 0;
- break;
- }
- QPointF e(num[0], num[1]);
- num += 2;
- count -= 2;
- QPointF c;
- if (lastMode == 'q' || lastMode == 'Q' ||
- lastMode == 't' || lastMode == 'T')
- c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c = QPointF(x, y);
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'a': {
- if (count < 7) {
- num += count;
- count = 0;
- break;
- }
- qreal rx = (*num++);
- qreal ry = (*num++);
- qreal xAxisRotation = (*num++);
- qreal largeArcFlag = (*num++);
- qreal sweepFlag = (*num++);
- qreal ex = (*num++) + offsetX;
- qreal ey = (*num++) + offsetY;
- count -= 7;
- qreal curx = x;
- qreal cury = y;
- pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
- int(sweepFlag), ex, ey, curx, cury);
-
- x = ex;
- y = ey;
- }
- break;
- case 'A': {
- if (count < 7) {
- num += count;
- count = 0;
- break;
- }
- qreal rx = (*num++);
- qreal ry = (*num++);
- qreal xAxisRotation = (*num++);
- qreal largeArcFlag = (*num++);
- qreal sweepFlag = (*num++);
- qreal ex = (*num++);
- qreal ey = (*num++);
- count -= 7;
- qreal curx = x;
- qreal cury = y;
- pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
- int(sweepFlag), ex, ey, curx, cury);
-
- x = ex;
- y = ey;
- }
- break;
- default:
- return false;
- }
- lastMode = pathElem.toLatin1();
- }
- }
- return true;
-}
-
void QSGContext2D::setPathString(const QString& path)
{
Q_D(QSGContext2D);
d->path = QPainterPath();
- parsePathDataFast(path, d->path);
+ QDeclarativeSvgParser::parsePathDataFast(path, d->path);
}
QList<int> QSGContext2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh)
diff --git a/src/declarative/items/qsganimation.cpp b/src/declarative/items/qsganimation.cpp
index 0822974397..eda5629eb9 100644
--- a/src/declarative/items/qsganimation.cpp
+++ b/src/declarative/items/qsganimation.cpp
@@ -43,6 +43,9 @@
#include "qsganimation_p_p.h"
#include "qsgstateoperations_p.h"
+#include <qdeclarativeproperty_p.h>
+#include <qdeclarativepath_p.h>
+
#include <QtDeclarative/qdeclarativeinfo.h>
#include <QtCore/qmath.h>
#include <QtCore/qsequentialanimationgroup.h>
@@ -439,4 +442,229 @@ void QSGAnchorAnimation::transition(QDeclarativeStateActions &actions,
}
}
+QSGPathAnimation::QSGPathAnimation(QObject *parent)
+: QDeclarativeAbstractAnimation(*(new QSGPathAnimationPrivate), parent)
+{
+ Q_D(QSGPathAnimation);
+ d->pa = new QDeclarativeBulkValueAnimator;
+ QDeclarative_setParent_noEvent(d->pa, this);
+}
+
+QSGPathAnimation::~QSGPathAnimation()
+{
+}
+
+int QSGPathAnimation::duration() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->pa->duration();
+}
+
+void QSGPathAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QSGPathAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+QEasingCurve QSGPathAnimation::easing() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->pa->easingCurve();
+}
+
+void QSGPathAnimation::setEasing(const QEasingCurve &e)
+{
+ Q_D(QSGPathAnimation);
+ if (d->pa->easingCurve() == e)
+ return;
+
+ d->pa->setEasingCurve(e);
+ emit easingChanged(e);
+}
+
+QDeclarativePath *QSGPathAnimation::path() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->path;
+}
+
+void QSGPathAnimation::setPath(QDeclarativePath *path)
+{
+ Q_D(QSGPathAnimation);
+ if (d->path == path)
+ return;
+
+ d->path = path;
+ emit pathChanged();
+}
+
+QSGItem *QSGPathAnimation::target() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->target;
+}
+
+void QSGPathAnimation::setTarget(QSGItem *target)
+{
+ Q_D(QSGPathAnimation);
+ if (d->target == target)
+ return;
+
+ d->target = target;
+ emit targetChanged();
+}
+
+QSGPathAnimation::Orientation QSGPathAnimation::orientation() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->orientation;
+}
+
+void QSGPathAnimation::setOrientation(Orientation orientation)
+{
+ Q_D(QSGPathAnimation);
+ if (d->orientation == orientation)
+ return;
+
+ d->orientation = orientation;
+ emit orientationChanged(d->orientation);
+}
+
+QPointF QSGPathAnimation::anchorPoint() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->anchorPoint;
+}
+
+void QSGPathAnimation::setAnchorPoint(const QPointF &point)
+{
+ Q_D(QSGPathAnimation);
+ if (d->anchorPoint == point)
+ return;
+
+ d->anchorPoint = point;
+ emit anchorPointChanged(point);
+}
+
+QAbstractAnimation *QSGPathAnimation::qtAnimation()
+{
+ Q_D(QSGPathAnimation);
+ return d->pa;
+}
+
+void QSGPathAnimation::transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QSGPathAnimation);
+ QSGPathAnimationUpdater *data = new QSGPathAnimationUpdater;
+
+ data->orientation = d->orientation;
+ data->anchorPoint = d->anchorPoint;
+ data->reverse = direction == Backward ? true : false;
+ data->fromSourced = false;
+ data->fromDefined = d->path ? !d->path->hasStartX() || !d->path->hasStartY() ? false : true : false; //### handle x/y separately, as well as endpoint specification?
+ int origModifiedSize = modified.count();
+
+ for (int i = 0; i < actions.count(); ++i) {
+ QDeclarativeAction &action = actions[i];
+ if (action.event)
+ continue;
+ if (action.specifiedObject == d->target && action.property.name() == QLatin1String("x")) {
+ data->toX = action.toValue.toReal();
+ modified << action.property;
+ action.fromValue = action.toValue;
+ }
+ if (action.specifiedObject == d->target && action.property.name() == QLatin1String("y")) {
+ data->toY = action.toValue.toReal();
+ modified << action.property;
+ action.fromValue = action.toValue;
+ }
+ }
+
+ if (d->target && d->path &&
+ (modified.count() > origModifiedSize || data->fromDefined)) {
+ data->target = d->target;
+ data->path = d->path;
+ if (!d->rangeIsSet) {
+ d->pa->setStartValue(qreal(0));
+ d->pa->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+ d->pa->setFromSourcedValue(&data->fromSourced);
+ d->pa->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ d->pa->setFromSourcedValue(0);
+ d->pa->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped);
+ delete data;
+ }
+}
+
+void QSGPathAnimationUpdater::setValue(qreal v)
+{
+ if (!fromSourced && !fromDefined) { //### check if !toDefined?
+ qreal startX = reverse ? toX + anchorPoint.x() : target->x() + anchorPoint.x();
+ qreal startY = reverse ? toY + anchorPoint.y() : target->y() + anchorPoint.y();
+ qreal endX = reverse ? target->x() + anchorPoint.x() : toX + anchorPoint.x();
+ qreal endY = reverse ? target->y() + anchorPoint.y() : toY + anchorPoint.y();
+
+ prevBez.isValid = false;
+ painterPath = path->createPath(QPointF(startX, startY), QPointF(endX, endY), QStringList(), pathLength, attributePoints);
+ fromSourced = true;
+ }
+
+ qreal angle;
+ bool fixed = orientation == QSGPathAnimation::Fixed;
+ QPointF currentPos = !painterPath.isEmpty() ? path->sequentialPointAt(painterPath, pathLength, attributePoints, prevBez, v, fixed ? 0 : &angle) : path->sequentialPointAt(v, fixed ? 0 : &angle);
+
+ //adjust position according to anchor point
+ if (!anchorPoint.isNull()) {
+ currentPos -= anchorPoint;
+ if ((reverse && v == 1.0) || (!reverse && v == 0.0)) {
+ if (!anchorPoint.isNull() && !fixed)
+ target->setTransformOriginPoint(anchorPoint);
+ }
+ }
+
+ //### too expensive to reconstruct properties each time?
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "x"), currentPos.x(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "y"), currentPos.y(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+
+ //adjust angle according to orientation
+ if (!fixed) {
+ switch (orientation) {
+ case QSGPathAnimation::RightFirst:
+ angle = -angle;
+ break;
+ case QSGPathAnimation::LeftFirst:
+ angle = -angle + 180;
+ break;
+ case QSGPathAnimation::BottomFirst:
+ angle = -angle + 270;
+ break;
+ case QSGPathAnimation::TopFirst:
+ angle = -angle + 450;
+ break;
+ default:
+ angle = 0;
+ break;
+ }
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "rotation"), angle, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+
+ //### resetting transform causes visual jump if ending on an angle
+// if ((reverse && v == 0.0) || (!reverse && v == 1.0)) {
+// if (!anchorPoint.isNull() && !fixed)
+// target->setTransformOriginPoint(QPointF());
+// }
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsganimation_p.h b/src/declarative/items/qsganimation_p.h
index ee3fe8d02d..6406b863a0 100644
--- a/src/declarative/items/qsganimation_p.h
+++ b/src/declarative/items/qsganimation_p.h
@@ -122,10 +122,72 @@ protected:
virtual QAbstractAnimation *qtAnimation();
};
+class QSGItem;
+class QDeclarativePath;
+class QSGPathAnimationPrivate;
+class Q_AUTOTEST_EXPORT QSGPathAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGPathAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(QSGItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged)
+
+public:
+ QSGPathAnimation(QObject *parent=0);
+ virtual ~QSGPathAnimation();
+
+ enum Orientation {
+ Fixed,
+ RightFirst,
+ LeftFirst,
+ BottomFirst,
+ TopFirst
+ };
+ Q_ENUMS(Orientation)
+
+ int duration() const;
+ void setDuration(int);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *);
+
+ QSGItem *target() const;
+ void setTarget(QSGItem *);
+
+ Orientation orientation() const;
+ void setOrientation(Orientation orientation);
+
+ QPointF anchorPoint() const;
+ void setAnchorPoint(const QPointF &point);
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void easingChanged(const QEasingCurve &);
+ void pathChanged();
+ void targetChanged();
+ void orientationChanged(Orientation);
+ void anchorPointChanged(const QPointF &);
+};
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QSGParentAnimation)
QML_DECLARE_TYPE(QSGAnchorAnimation)
+QML_DECLARE_TYPE(QSGPathAnimation)
QT_END_HEADER
diff --git a/src/declarative/items/qsganimation_p_p.h b/src/declarative/items/qsganimation_p_p.h
index 6f26f35234..e26dbbd9fb 100644
--- a/src/declarative/items/qsganimation_p_p.h
+++ b/src/declarative/items/qsganimation_p_p.h
@@ -56,6 +56,7 @@
#include "qsganimation_p.h"
+#include <private/qdeclarativepath_p.h>
#include <private/qdeclarativeanimation_p_p.h>
QT_BEGIN_NAMESPACE
@@ -92,6 +93,46 @@ public:
QList<QSGItem*> targets;
};
+class QSGPathAnimationUpdater : public QDeclarativeBulkValueUpdater
+{
+public:
+ QDeclarativePath *path;
+
+ QPainterPath painterPath;
+ QDeclarativeCachedBezier prevBez;
+ qreal pathLength;
+ QList<QDeclarativePath::AttributePoint> attributePoints;
+
+ QSGItem *target;
+ bool reverse;
+ bool fromSourced;
+ bool fromDefined;
+ qreal toX;
+ qreal toY;
+ QSGPathAnimation::Orientation orientation;
+ QPointF anchorPoint;
+ QSGPathAnimationUpdater() : path(0), target(0), reverse(false),
+ fromSourced(false), fromDefined(false), toX(0), toY(0), orientation(QSGPathAnimation::Fixed) {}
+ ~QSGPathAnimationUpdater() {}
+ void setValue(qreal v);
+};
+
+class QSGPathAnimationPrivate : public QDeclarativeAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QSGPathAnimation)
+public:
+ QSGPathAnimationPrivate() : path(0), target(0),
+ rangeIsSet(false), orientation(QSGPathAnimation::Fixed), pa(0) {}
+
+ QDeclarativePath *path;
+ QSGItem *target;
+ bool rangeIsSet;
+ QSGPathAnimation::Orientation orientation;
+ QPointF anchorPoint;
+ QDeclarativeBulkValueAnimator *pa;
+};
+
+
QT_END_NAMESPACE
#endif // QSGANIMATION_P_H
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 2f663681ae..3e3a8b5842 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -1537,7 +1537,7 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
itemPriv->transforms.at(ii)->applyTo(&matrix);
if (itemPriv->scale != 1. || itemPriv->rotation != 0.) {
- QPointF origin = itemPriv->computeTransformOrigin();
+ QPointF origin = item->transformOriginPoint();
matrix.translate(origin.x(), origin.y());
if (itemPriv->scale != 1.)
matrix.scale(itemPriv->scale, itemPriv->scale);
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index 21474be8d9..e207e4bfd0 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -175,6 +175,7 @@ QSGFlickablePrivate::QSGFlickablePrivate()
, hMoved(false), vMoved(false)
, movingHorizontally(false), movingVertically(false)
, stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
+ , pixelAligned(false)
, deceleration(QML_FLICK_DEFAULTDECELERATION)
, maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100)
, delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400)
@@ -778,6 +779,21 @@ void QSGFlickable::setFlickableDirection(FlickableDirection direction)
}
}
+bool QSGFlickable::pixelAligned() const
+{
+ Q_D(const QSGFlickable);
+ return d->pixelAligned;
+}
+
+void QSGFlickable::setPixelAligned(bool align)
+{
+ Q_D(QSGFlickable);
+ if (align != d->pixelAligned) {
+ d->pixelAligned = align;
+ emit pixelAlignedChanged();
+ }
+}
+
void QSGFlickablePrivate::handleMousePressEvent(QMouseEvent *event)
{
Q_Q(QSGFlickable);
@@ -1081,14 +1097,15 @@ void QSGFlickablePrivate::clearDelayedPress()
}
}
+//XXX pixelAligned ignores the global position of the Flickable, i.e. assumes Flickable itself is pixel aligned.
void QSGFlickablePrivate::setViewportX(qreal x)
{
- contentItem->setX(x);
+ contentItem->setX(pixelAligned ? qRound(x) : x);
}
void QSGFlickablePrivate::setViewportY(qreal y)
{
- contentItem->setY(y);
+ contentItem->setY(pixelAligned ? qRound(y) : y);
}
void QSGFlickable::timerEvent(QTimerEvent *event)
diff --git a/src/declarative/items/qsgflickable_p.h b/src/declarative/items/qsgflickable_p.h
index 14f5232cd8..d638b921c5 100644
--- a/src/declarative/items/qsgflickable_p.h
+++ b/src/declarative/items/qsgflickable_p.h
@@ -90,6 +90,8 @@ class Q_AUTOTEST_EXPORT QSGFlickable : public QSGItem
Q_PROPERTY(QSGFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+ Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
+
Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
Q_PROPERTY(QDeclarativeListProperty<QSGItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
@@ -156,6 +158,9 @@ public:
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
+ bool pixelAligned() const;
+ void setPixelAligned(bool align);
+
Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center);
Q_INVOKABLE void returnToBounds();
@@ -188,6 +193,7 @@ Q_SIGNALS:
void flickEnded();
void dragStarted();
void dragEnded();
+ void pixelAlignedChanged();
protected:
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
diff --git a/src/declarative/items/qsgflickable_p_p.h b/src/declarative/items/qsgflickable_p_p.h
index 3ac6d87864..21c31060b8 100644
--- a/src/declarative/items/qsgflickable_p_p.h
+++ b/src/declarative/items/qsgflickable_p_p.h
@@ -168,6 +168,7 @@ public:
bool pressed : 1;
bool interactive : 1;
bool calcVelocity : 1;
+ bool pixelAligned : 1;
QElapsedTimer lastPosTime;
QPointF lastPos;
QPointF pressPos;
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index bc4954a168..e2fe5cd9c8 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -160,12 +160,15 @@ public:
FxViewItem *snapItemAt(qreal pos) const;
int snapIndex() const;
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
virtual FxViewItem *newViewItem(int index, QSGItem *item);
virtual void repositionPackageItemAt(QSGItem *item, int index);
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
+ virtual void resetFirstItemPosition();
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &items, const QList<FxViewItem *> &movedBackwards);
virtual void createHighlight();
virtual void updateHighlight();
@@ -173,6 +176,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems();
+ bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *>*, FxViewItem *);
virtual qreal headerSize() const;
virtual qreal footerSize() const;
@@ -383,7 +387,7 @@ FxViewItem *QSGGridViewPrivate::newViewItem(int modelIndex, QSGItem *item)
return new FxGridItemSG(item, q, false);
}
-bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
+bool QSGGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
{
int colPos = colPosAt(visibleIndex);
int rowPos = rowPosAt(visibleIndex);
@@ -475,7 +479,7 @@ bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer
return changed;
}
-bool QSGGridViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+bool QSGGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxGridItemSG *item = 0;
bool changed = false;
@@ -560,6 +564,24 @@ void QSGGridViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
}
}
+void QSGGridViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
+{
+ FxGridItemSG *toGridItem = static_cast<FxGridItemSG*>(toItem);
+ static_cast<FxGridItemSG*>(item)->setPosition(toGridItem->colPos(), toGridItem->rowPos());
+}
+
+void QSGGridViewPrivate::resetFirstItemPosition()
+{
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.first());
+ item->setPosition(0, 0);
+}
+
+void QSGGridViewPrivate::moveItemBy(FxViewItem *item, const QList<FxViewItem *> &forwards, const QList<FxViewItem *> &backwards)
+{
+ int moveCount = forwards.count() - backwards.count();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(item);
+ gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
+}
void QSGGridViewPrivate::createHighlight()
{
@@ -602,6 +624,8 @@ void QSGGridViewPrivate::createHighlight()
void QSGGridViewPrivate::updateHighlight()
{
+ applyPendingChanges();
+
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
bool strictHighlight = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
@@ -750,7 +774,7 @@ void QSGGridViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (item == q) {
if (newGeometry.height() != oldGeometry.height() || newGeometry.width() != oldGeometry.width()) {
updateViewport();
- scheduleLayout();
+ q->polish();
}
}
}
@@ -1370,6 +1394,7 @@ void QSGGridView::setCellWidth(int cellWidth)
d->cellWidth = qMax(1, cellWidth);
d->updateViewport();
emit cellWidthChanged();
+ d->forceLayout = true;
d->layout();
}
}
@@ -1387,6 +1412,7 @@ void QSGGridView::setCellHeight(int cellHeight)
d->cellHeight = qMax(1, cellHeight);
d->updateViewport();
emit cellHeightChanged();
+ d->forceLayout = true;
d->layout();
}
}
@@ -1688,349 +1714,96 @@ void QSGGridView::moveCurrentIndexRight()
}
}
-
-void QSGGridView::itemsInserted(int modelIndex, int count)
+bool QSGGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, QList<FxViewItem *> *movedBackwards, QList<FxViewItem *> *addedItems, FxViewItem *firstVisible)
{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
+ Q_Q(QSGGridView);
+
+ int modelIndex = change.index;
+ int count = change.count;
+
+ int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
- int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
if (index < 0) {
- int i = d->visibleItems.count() - 1;
- while (i > 0 && d->visibleItems.at(i)->index == -1)
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
--i;
- if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ if (visibleItems.at(i)->index + 1 == modelIndex) {
// Special case of appending an item to the model.
- index = d->visibleIndex + d->visibleItems.count();
+ index = visibleIndex + visibleItems.count();
} else {
- if (modelIndex <= d->visibleIndex) {
+ if (modelIndex <= visibleIndex) {
// Insert before visible items
- d->visibleIndex += count;
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ visibleIndex += count;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
}
- if (d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem)
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- d->scheduleLayout();
- d->itemCount += count;
- emit countChanged();
- return;
+ return true;
}
}
int insertCount = count;
- if (index < d->visibleIndex && d->visibleItems.count()) {
- insertCount -= d->visibleIndex - index;
- index = d->visibleIndex;
- modelIndex = d->visibleIndex;
+ if (index < visibleIndex && visibleItems.count()) {
+ insertCount -= visibleIndex - index;
+ index = visibleIndex;
+ modelIndex = visibleIndex;
}
- qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+width()+1 : d->position();
- int to = d->buffer+tempPos+d->size()-1;
+ qreal tempPos = isRightToLeftTopToBottom() ? -position()-size()+q->width()+1 : position();
+ int to = buffer+tempPos+size()-1;
int colPos = 0;
int rowPos = 0;
- if (d->visibleItems.count()) {
- index -= d->visibleIndex;
- if (index < d->visibleItems.count()) {
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index));
+ if (visibleItems.count()) {
+ index -= visibleIndex;
+ if (index < visibleItems.count()) {
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index));
colPos = gridItem->colPos();
rowPos = gridItem->rowPos();
} else {
// appending items to visible list
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index-1));
- colPos = gridItem->colPos() + d->colSize();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index-1));
+ colPos = gridItem->colPos() + colSize();
rowPos = gridItem->rowPos();
- if (colPos > d->colSize() * (d->columns-1)) {
+ if (colPos > colSize() * (columns-1)) {
colPos = 0;
- rowPos += d->rowSize();
+ rowPos += rowSize();
}
}
}
// Update the indexes of the following visible items.
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
- bool addedVisible = false;
- QList<FxGridItemSG*> added;
int i = 0;
- while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
+ bool prevAddedCount = addedItems->count();
+ while (i < insertCount && rowPos <= to + rowSize()*(columns - (colPos/colSize()))/qreal(columns)) {
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- FxGridItemSG *item = static_cast<FxGridItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(index, item);
- item->setPosition(colPos, rowPos);
- added.append(item);
- colPos += d->colSize();
- if (colPos > d->colSize() * (d->columns-1)) {
+ if (!item)
+ item = createItem(modelIndex + i);
+ visibleItems.insert(index, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
colPos = 0;
- rowPos += d->rowSize();
+ rowPos += rowSize();
}
++index;
++i;
}
- if (i < insertCount) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index) {
- d->releaseItem(d->visibleItems.takeLast());
- }
- }
-
- // update visibleIndex
- d->visibleIndex = 0;
- for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- if (d->itemCount && d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem) {
- d->currentItem->index = d->currentIndex;
- static_cast<FxGridItemSG*>(d->currentItem)->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
- }
- emit currentIndexChanged();
- } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
- setCurrentIndex(0);
- }
-
- // everything is in order now - emit add() signal
- for (int j = 0; j < added.count(); ++j)
- added.at(j)->attached->emitAdd();
-
- d->itemCount += count;
- emit countChanged();
-}
-
-void QSGGridView::itemsRemoved(int modelIndex, int count)
-{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
-
- d->itemCount -= count;
- bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
- bool removedVisible = false;
-
- // Remove the items from the visible list, skipping anything already marked for removal
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index == -1 || item->index < modelIndex) {
- // already removed, or before removed items
- if (item->index < modelIndex && !removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- ++it;
- } else if (item->index >= modelIndex + count) {
- // after removed items
- item->index -= count;
- ++it;
- } else {
- // removed item
- if (!removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- item->attached->emitRemove();
- if (item->attached->delayRemove()) {
- item->index = -1;
- connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
- ++it;
- } else {
- it = d->visibleItems.erase(it);
- d->releaseItem(item);
- }
- }
- }
-
- // update visibleIndex
- d->visibleIndex = 0;
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- // fix current
- if (d->currentIndex >= modelIndex + count) {
- d->currentIndex -= count;
- if (d->currentItem)
- d->currentItem->index -= count;
- emit currentIndexChanged();
- } else if (currentRemoved) {
- // current item has been removed.
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
- d->currentIndex = -1;
- if (d->itemCount)
- d->updateCurrent(qMin(modelIndex, d->itemCount-1));
- else
- emit currentIndexChanged();
- }
-
- if (removedVisible && d->visibleItems.isEmpty()) {
- d->timeline.clear();
- if (d->itemCount == 0) {
- d->setPosition(d->contentStartPosition());
- d->updateHeader();
- d->updateFooter();
- }
- }
-
- emit countChanged();
-}
-
-
-void QSGGridView::itemsMoved(int from, int to, int count)
-{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->isValid())
- return;
- d->updateUnrequestedIndexes();
-
- if (d->visibleItems.isEmpty()) {
- d->refill();
- return;
- }
-
- d->moveReason = QSGGridViewPrivate::Other;
-
- bool movingBackwards = from > to;
- d->adjustMoveParameters(&from, &to, &count);
-
- QHash<int,FxGridItemSG*> moved;
- int moveByCount = 0;
- FxGridItemSG *firstVisible = static_cast<FxGridItemSG*>(d->firstVisibleItem());
- int firstItemIndex = firstVisible ? firstVisible->index : -1;
-
- // if visibleItems.first() is above the content start pos, and the items
- // beneath it are moved, ensure this first item is later repositioned correctly
- // (to above the next visible item) so that subsequent layout() is correct
- bool repositionFirstItem = firstVisible
- && d->visibleItems.first()->position() < firstVisible->position()
- && from > d->visibleItems.first()->index;
-
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index >= from && item->index < from + count) {
- // take the items that are moving
- item->index += (to-from);
- moved.insert(item->index, static_cast<FxGridItemSG*>(item));
- if (repositionFirstItem)
- moveByCount++;
- it = d->visibleItems.erase(it);
- } else {
- if (item->index > from && item->index != -1) {
- // move everything after the moved items.
- item->index -= count;
- if (item->index < d->visibleIndex)
- d->visibleIndex = item->index;
- }
- ++it;
- }
- }
-
- int movedCount = 0;
- int endIndex = d->visibleIndex;
- it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (movedCount < count && item->index >= to && item->index < to + count) {
- // place items in the target position, reusing any existing items
- int targetIndex = item->index + movedCount;
- FxGridItemSG *movedItem = moved.take(targetIndex);
- if (!movedItem)
- movedItem = static_cast<FxGridItemSG*>(d->createItem(targetIndex));
- it = d->visibleItems.insert(it, movedItem);
- ++it;
- ++movedCount;
- } else {
- if (item->index != -1) {
- if (item->index >= to) {
- // update everything after the moved items.
- item->index += count;
- }
- endIndex = item->index;
- }
- ++it;
- }
- }
-
- // If we have moved items to the end of the visible items
- // then add any existing moved items that we have
- while (FxGridItemSG *item = moved.take(endIndex+1)) {
- d->visibleItems.append(item);
- ++endIndex;
- }
-
- // update visibleIndex
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
- // if first visible item is moving but another item is moving up to replace it,
- // do this positioning now to avoid shifting all content forwards
- if (movingBackwards && firstItemIndex >= 0) {
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index == firstItemIndex) {
- static_cast<FxGridItemSG*>(*it)->setPosition(firstVisible->colPos(),
- firstVisible->rowPos());
- break;
- }
- }
- }
-
- // Fix current index
- if (d->currentIndex >= 0 && d->currentItem) {
- int oldCurrent = d->currentIndex;
- d->currentIndex = d->model->indexOf(d->currentItem->item, this);
- if (oldCurrent != d->currentIndex) {
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- }
-
- // Whatever moved items remain are no longer visible items.
- while (moved.count()) {
- int idx = moved.begin().key();
- FxGridItemSG *item = moved.take(idx);
- if (d->currentItem && item->item == d->currentItem->item)
- item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
- d->releaseItem(item);
- }
-
- // Ensure we don't cause an ugly list scroll.
- if (d->visibleItems.count() && moveByCount > 0) {
- FxGridItemSG *first = static_cast<FxGridItemSG*>(d->visibleItems.first());
- first->setPosition(first->colPos(), first->rowPos() + ((moveByCount / d->columns) * d->rowSize()));
- }
-
- d->layout();
+ return addedItems->count() > prevAddedCount;
}
/*!
@@ -2098,6 +1871,7 @@ void QSGGridView::itemsMoved(int from, int to, int count)
\bold Note: methods should only be called after the Component has completed.
*/
+
QSGGridViewAttached *QSGGridView::qmlAttachedProperties(QObject *obj)
{
return new QSGGridViewAttached(obj);
diff --git a/src/declarative/items/qsggridview_p.h b/src/declarative/items/qsggridview_p.h
index ae4ce346db..1cdf81d213 100644
--- a/src/declarative/items/qsggridview_p.h
+++ b/src/declarative/items/qsggridview_p.h
@@ -109,11 +109,6 @@ Q_SIGNALS:
protected:
virtual void viewportMoved();
virtual void keyPressEvent(QKeyEvent *);
-
-private Q_SLOTS:
- void itemsInserted(int index, int count);
- void itemsRemoved(int index, int count);
- void itemsMoved(int from, int to, int count);
};
class QSGGridViewAttached : public QSGItemViewAttached
diff --git a/src/declarative/items/qsgimagebase.cpp b/src/declarative/items/qsgimagebase.cpp
index f8f2183a15..5c6334de66 100644
--- a/src/declarative/items/qsgimagebase.cpp
+++ b/src/declarative/items/qsgimagebase.cpp
@@ -163,6 +163,12 @@ void QSGImageBase::setCache(bool cache)
load();
}
+QPixmap QSGImageBase::pixmap() const
+{
+ Q_D(const QSGImageBase);
+ return d->pix.pixmap();
+}
+
void QSGImageBase::setMirror(bool mirror)
{
Q_D(QSGImageBase);
diff --git a/src/declarative/items/qsgimagebase_p.h b/src/declarative/items/qsgimagebase_p.h
index 567c46d30b..e17ca3b059 100644
--- a/src/declarative/items/qsgimagebase_p.h
+++ b/src/declarative/items/qsgimagebase_p.h
@@ -79,6 +79,8 @@ public:
bool cache() const;
void setCache(bool);
+ QPixmap pixmap() const;
+
virtual void setSourceSize(const QSize&);
QSize sourceSize() const;
void resetSourceSize();
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index addb046e62..f3de1a6b3f 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -3192,6 +3192,18 @@ void QSGItemPrivate::setState(const QString &state)
_states()->setState(state);
}
+QString QSGItem::state() const
+{
+ Q_D(const QSGItem);
+ return d->state();
+}
+
+void QSGItem::setState(const QString &state)
+{
+ Q_D(QSGItem);
+ d->setState(state);
+}
+
QDeclarativeListProperty<QSGTransform> QSGItem::transform()
{
Q_D(QSGItem);
@@ -3469,9 +3481,21 @@ void QSGItem::setTransformOrigin(TransformOrigin origin)
QPointF QSGItem::transformOriginPoint() const
{
Q_D(const QSGItem);
+ if (!d->transformOriginPoint.isNull())
+ return d->transformOriginPoint;
return d->computeTransformOrigin();
}
+void QSGItem::setTransformOriginPoint(const QPointF &point)
+{
+ Q_D(QSGItem);
+ if (d->transformOriginPoint == point)
+ return;
+
+ d->transformOriginPoint = point;
+ d->dirty(QSGItemPrivate::TransformOrigin);
+}
+
qreal QSGItem::z() const
{
Q_D(const QSGItem);
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index 9cd549d3b8..6653a4fe1b 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -119,7 +119,7 @@ class Q_DECLARATIVE_EXPORT QSGItem : public QObject, public QDeclarativeParserSt
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QDeclarativeListProperty<QDeclarativeState> states READ states DESIGNABLE false)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitions DESIGNABLE false)
- Q_PRIVATE_PROPERTY(QSGItem::d_func(), QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QSGAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QSGAnchorLine left READ left CONSTANT FINAL)
@@ -205,6 +205,9 @@ public:
bool clip() const;
void setClip(bool);
+ QString state() const;
+ void setState(const QString &);
+
qreal baselineOffset() const;
void setBaselineOffset(qreal);
@@ -232,6 +235,7 @@ public:
TransformOrigin transformOrigin() const;
void setTransformOrigin(TransformOrigin);
QPointF transformOriginPoint() const;
+ void setTransformOriginPoint(const QPointF &);
qreal z() const;
void setZ(qreal);
diff --git a/src/declarative/items/qsgitem_p.h b/src/declarative/items/qsgitem_p.h
index 513aba2bf6..e48c1043e5 100644
--- a/src/declarative/items/qsgitem_p.h
+++ b/src/declarative/items/qsgitem_p.h
@@ -300,6 +300,8 @@ public:
Qt::MouseButtons acceptedMouseButtons;
Qt::InputMethodHints imHints;
+ QPointF transformOriginPoint;
+
virtual qreal getImplicitWidth() const;
virtual qreal getImplicitHeight() const;
virtual void implicitWidthChanged();
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 0d147d31fc..2e24155b7d 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -61,6 +61,7 @@
#include "qsggridview_p.h"
#include "qsgpathview_p.h"
#include <private/qdeclarativepath_p.h>
+#include <private/qdeclarativepathinterpolator_p.h>
#include "qsgpositioners_p.h"
#include "qsgrepeater_p.h"
#include "qsgloader_p.h"
@@ -125,6 +126,9 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QDeclarativePathLine>(uri,major,minor,"PathLine");
qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
+ qmlRegisterType<QDeclarativePathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
+ qmlRegisterType<QDeclarativePathArc>("QtQuick",2,0,"PathArc");
+ qmlRegisterType<QDeclarativePathSvg>("QtQuick",2,0,"PathSvg");
qmlRegisterType<QSGPathView>(uri,major,minor,"PathView");
qmlRegisterUncreatableType<QSGBasePositioner>(uri,major,minor,"Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
@@ -172,8 +176,8 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGShaderEffectItem>("QtQuick", 2, 0, "ShaderEffectItem"); // TODO: Remove after grace period.
qmlRegisterType<QSGShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
qmlRegisterType<QSGShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
- qmlRegisterUncreatableType<QSGShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QSGShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh.")); // TODO: Remove after grace period.
- qmlRegisterType<QSGGridMesh>("QtQuick", 2, 0, "GridMesh"); // TODO: Remove after grace period.
+ qmlRegisterUncreatableType<QSGShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QSGShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
+ qmlRegisterType<QSGGridMesh>("QtQuick", 2, 0, "GridMesh");
qmlRegisterUncreatableType<QSGPaintedItem>("QtQuick", 2, 0, "PaintedItem", QSGPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
@@ -189,6 +193,8 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGAnchorSet>();
qmlRegisterType<QSGAnchorAnimation>(uri, major, minor,"AnchorAnimation");
qmlRegisterType<QSGParentAnimation>(uri, major, minor,"ParentAnimation");
+ qmlRegisterType<QSGPathAnimation>("QtQuick",2,0,"PathAnimation");
+ qmlRegisterType<QDeclarativePathInterpolator>("QtQuick",2,0,"PathInterpolator");
qmlRegisterType<QSGDragTarget>("QtQuick", 2, 0, "DragTarget");
qmlRegisterType<QSGDragTargetEvent>();
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
index 5543f12f6d..2b3f51b648 100644
--- a/src/declarative/items/qsgitemview.cpp
+++ b/src/declarative/items/qsgitemview.cpp
@@ -58,6 +58,102 @@ FxViewItem::~FxViewItem()
}
}
+
+QSGItemViewChangeSet::QSGItemViewChangeSet()
+ : active(false)
+{
+ reset();
+}
+
+bool QSGItemViewChangeSet::hasPendingChanges() const
+{
+ return !pendingChanges.isEmpty();
+}
+
+void QSGItemViewChangeSet::doInsert(int index, int count)
+{
+ pendingChanges.insert(index, count);
+
+ if (newCurrentIndex >= index) {
+ // adjust current item index
+ newCurrentIndex += count;
+ currentChanged = true;
+ } else if (newCurrentIndex < 0) {
+ newCurrentIndex = 0;
+ currentChanged = true;
+ }
+
+ itemCount += count;
+}
+
+void QSGItemViewChangeSet::doRemove(int index, int count)
+{
+ itemCount -= count;
+ pendingChanges.remove(index, count);
+
+ if (newCurrentIndex >= index + count) {
+ newCurrentIndex -= count;
+ currentChanged = true;
+ } else if (newCurrentIndex >= index && newCurrentIndex < index + count) {
+ // current item has been removed.
+ currentRemoved = true;
+ newCurrentIndex = -1;
+ if (itemCount)
+ newCurrentIndex = qMin(index, itemCount-1);
+ currentChanged = true;
+ }
+}
+
+void QSGItemViewChangeSet::doMove(int from, int to, int count)
+{
+ pendingChanges.move(from, to, count);
+
+ if (to > from) {
+ if (newCurrentIndex >= from) {
+ if (newCurrentIndex < from + count)
+ newCurrentIndex += (to-from);
+ else if (newCurrentIndex < to + count)
+ newCurrentIndex -= count;
+ }
+ currentChanged = true;
+ } else if (to < from) {
+ if (newCurrentIndex >= to) {
+ if (newCurrentIndex >= from && newCurrentIndex < from + count)
+ newCurrentIndex -= (from-to);
+ else if (newCurrentIndex < from)
+ newCurrentIndex += count;
+ }
+ currentChanged = true;
+ }
+}
+
+void QSGItemViewChangeSet::QSGItemViewChangeSet::doChange(int index, int count)
+{
+ pendingChanges.change(index, count);
+}
+
+void QSGItemViewChangeSet::prepare(int currentIndex, int count)
+{
+ if (active)
+ return;
+ reset();
+ active = true;
+ itemCount = count;
+ newCurrentIndex = currentIndex;
+}
+
+void QSGItemViewChangeSet::reset()
+{
+ itemCount = 0;
+ newCurrentIndex = -1;
+ pendingChanges.clear();
+ removedItems.clear();
+ active = false;
+ currentChanged = false;
+ currentRemoved = false;
+}
+
+
QSGItemView::QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent)
: QSGFlickable(dd, parent)
{
@@ -81,6 +177,7 @@ QSGItem *QSGItemView::currentItem() const
Q_D(const QSGItemView);
if (!d->currentItem)
return 0;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->currentItem->item;
}
@@ -213,14 +310,16 @@ void QSGItemView::setDelegate(QDeclarativeComponent *delegate)
int QSGItemView::count() const
{
Q_D(const QSGItemView);
- if (d->model)
- return d->model->count();
- return 0;
+ if (!d->model)
+ return 0;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
+ return d->model->count();
}
int QSGItemView::currentIndex() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->currentIndex;
}
@@ -230,6 +329,8 @@ void QSGItemView::setCurrentIndex(int index)
if (d->requestedIndex >= 0) // currently creating item
return;
d->currentIndexCleared = (index == -1);
+
+ d->applyPendingChanges();
if (index == d->currentIndex)
return;
if (isComponentComplete() && d->isValid()) {
@@ -313,6 +414,7 @@ QDeclarativeComponent *QSGItemView::header() const
QSGItem *QSGItemView::headerItem() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->header ? d->header->item : 0;
}
@@ -320,6 +422,7 @@ void QSGItemView::setHeader(QDeclarativeComponent *headerComponent)
{
Q_D(QSGItemView);
if (d->headerComponent != headerComponent) {
+ d->applyPendingChanges();
delete d->header;
d->header = 0;
d->headerComponent = headerComponent;
@@ -348,6 +451,7 @@ QDeclarativeComponent *QSGItemView::footer() const
QSGItem *QSGItemView::footerItem() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->footer ? d->footer->item : 0;
}
@@ -355,6 +459,7 @@ void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
{
Q_D(QSGItemView);
if (d->footerComponent != footerComponent) {
+ d->applyPendingChanges();
delete d->footer;
d->footer = 0;
d->footerComponent = footerComponent;
@@ -373,6 +478,7 @@ void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
QDeclarativeComponent *QSGItemView::highlight() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->highlightComponent;
}
@@ -380,6 +486,7 @@ void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
{
Q_D(QSGItemView);
if (highlightComponent != d->highlightComponent) {
+ d->applyPendingChanges();
d->highlightComponent = highlightComponent;
d->createHighlight();
if (d->currentItem)
@@ -391,9 +498,8 @@ void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
QSGItem *QSGItemView::highlightItem() const
{
Q_D(const QSGItemView);
- if (!d->highlight)
- return 0;
- return d->highlight->item;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
+ return d->highlight ? d->highlight->item : 0;
}
bool QSGItemView::highlightFollowsCurrentItem() const
@@ -506,10 +612,10 @@ void QSGItemViewPrivate::positionViewAtIndex(int index, int mode)
return;
if (mode < QSGItemView::Beginning || mode > QSGItemView::Contain)
return;
+
+ applyPendingChanges();
int idx = qMax(qMin(index, model->count()-1), 0);
- if (layoutScheduled)
- layout();
qreal pos = isContentFlowReversed() ? -position() - size() : position();
FxViewItem *item = visibleItem(idx);
qreal maxExtent;
@@ -614,6 +720,12 @@ int QSGItemView::indexAt(qreal x, qreal y) const
return -1;
}
+void QSGItemViewPrivate::applyPendingChanges()
+{
+ Q_Q(QSGItemView);
+ if (q->isComponentComplete() && currentChanges.hasPendingChanges())
+ layout();
+}
// for debugging only
void QSGItemViewPrivate::checkVisible() const
@@ -629,8 +741,6 @@ void QSGItemViewPrivate::checkVisible() const
}
}
-
-
void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_Q(QSGItemView);
@@ -638,10 +748,19 @@ void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (!q->isComponentComplete())
return;
- if (header && header->item == item)
+ if (header && header->item == item) {
updateHeader();
- else if (footer && footer->item == item)
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (!q->isMoving() && !q->isFlicking())
+ fixupPosition();
+ } else if (footer && footer->item == item) {
updateFooter();
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (!q->isMoving() && !q->isFlicking())
+ fixupPosition();
+ }
if (currentItem && currentItem->item == item)
updateHighlight();
@@ -665,14 +784,55 @@ void QSGItemView::destroyRemoved()
// Correct the positioning of the items
d->updateSections();
+ d->forceLayout = true;
d->layout();
}
-void QSGItemView::itemsChanged(int, int)
+void QSGItemView::itemsInserted(int index, int count)
{
Q_D(QSGItemView);
- d->updateSections();
- d->layout();
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doInsert(index, count);
+ polish();
+}
+
+void QSGItemView::itemsRemoved(int index, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doRemove(index, count);
+ polish();
+}
+
+void QSGItemView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ if (from == to || count <= 0 || from < 0 || to < 0)
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doMove(from, to, count);
+ polish();
+}
+
+void QSGItemView::itemsChanged(int index, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doChange(index, count);
+ polish();
}
void QSGItemView::modelReset()
@@ -796,7 +956,6 @@ void QSGItemView::trackedPositionChanged()
}
}
-
void QSGItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QSGItemView);
@@ -814,7 +973,7 @@ qreal QSGItemView::minYExtent() const
if (d->minExtentDirty) {
d->minExtent = -d->startPosition();
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->minExtent += d->headerSize();
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += d->highlightRangeStart;
@@ -885,7 +1044,7 @@ qreal QSGItemView::minXExtent() const
endPositionFirstItem = d->endPositionAt(0);
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->minExtent += d->headerSize();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
@@ -934,7 +1093,7 @@ qreal QSGItemView::maxXExtent() const
d->maxExtent = -(d->endPosition() - width());
}
if (d->isContentFlowReversed()) {
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->maxExtent -= d->headerSize();
} else {
if (d->footer)
@@ -1017,7 +1176,7 @@ QSGItemViewPrivate::QSGItemViewPrivate()
, headerComponent(0), header(0), footerComponent(0), footer(0)
, minExtent(0), maxExtent(0)
, ownModel(false), wrap(false), lazyRelease(false), deferredRelease(false)
- , layoutScheduled(false), inViewportMoved(false), currentIndexCleared(false)
+ , inApplyModelChanges(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, minExtentDirty(true), maxExtentDirty(true)
{
@@ -1082,7 +1241,7 @@ FxViewItem *QSGItemViewPrivate::firstVisibleItem() const {
const qreal pos = isContentFlowReversed() ? -position()-size() : position();
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
- if (item->index != -1 && item->endPosition() >= pos)
+ if (item->index != -1 && item->endPosition() > pos)
return item;
}
return visibleItems.count() ? visibleItems.first() : 0;
@@ -1105,18 +1264,6 @@ int QSGItemViewPrivate::mapFromModel(int modelIndex) const
return -1; // Not in visibleList
}
-void QSGItemViewPrivate::adjustMoveParameters(int *from, int *to, int *count) const
-{
- if (*from > *to) {
- // Only move forwards - flip if backwards moving
- int tfrom = *from;
- int tto = *to;
- *from = tto;
- *to = tto + *count;
- *count = tfrom - tto;
- }
-}
-
void QSGItemViewPrivate::init()
{
Q_Q(QSGItemView);
@@ -1130,6 +1277,8 @@ void QSGItemViewPrivate::init()
void QSGItemViewPrivate::updateCurrent(int modelIndex)
{
Q_Q(QSGItemView);
+ applyPendingChanges();
+
if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
currentItem->attached->setIsCurrentItem(false);
@@ -1168,6 +1317,7 @@ void QSGItemViewPrivate::updateCurrent(int modelIndex)
void QSGItemViewPrivate::clear()
{
+ currentChanges.reset();
timeline.clear();
for (int i = 0; i < visibleItems.count(); ++i)
@@ -1207,6 +1357,9 @@ void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
if (!isValid() || !q->isComponentComplete())
return;
+ currentChanges.reset();
+
+ int prevCount = itemCount;
itemCount = model->count();
qreal bufferFrom = from - buffer;
qreal bufferTo = to + buffer;
@@ -1240,12 +1393,15 @@ void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
lazyRelease = false;
+ if (prevCount != itemCount)
+ emit q->countChanged();
}
void QSGItemViewPrivate::regenerate()
{
Q_Q(QSGItemView);
if (q->isComponentComplete()) {
+ currentChanges.reset();
delete header;
header = 0;
delete footer;
@@ -1260,15 +1416,6 @@ void QSGItemViewPrivate::regenerate()
}
}
-void QSGItemViewPrivate::scheduleLayout()
-{
- Q_Q(QSGItemView);
- if (!layoutScheduled) {
- layoutScheduled = true;
- q->polish();
- }
-}
-
void QSGItemViewPrivate::updateViewport()
{
Q_Q(QSGItemView);
@@ -1283,13 +1430,16 @@ void QSGItemViewPrivate::updateViewport()
void QSGItemViewPrivate::layout()
{
Q_Q(QSGItemView);
- layoutScheduled = false;
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartPosition());
return;
}
+ if (!applyModelChanges() && !forceLayout)
+ return;
+ forceLayout = false;
+
layoutVisibleItems();
refill();
@@ -1297,6 +1447,7 @@ void QSGItemViewPrivate::layout()
maxExtentDirty = true;
updateHighlight();
+
if (!q->isMoving() && !q->isFlicking()) {
fixupPosition();
refill();
@@ -1308,6 +1459,134 @@ void QSGItemViewPrivate::layout()
updateUnrequestedPositions();
}
+bool QSGItemViewPrivate::applyModelChanges()
+{
+ Q_Q(QSGItemView);
+ if (!q->isComponentComplete() || !currentChanges.hasPendingChanges() || inApplyModelChanges)
+ return false;
+ inApplyModelChanges = true;
+
+ updateUnrequestedIndexes();
+ moveReason = QSGItemViewPrivate::Other;
+
+ int prevCount = itemCount;
+ bool removedVisible = false;
+
+ FxViewItem *firstVisible = firstVisibleItem();
+ FxViewItem *origVisibleItemsFirst = visibleItems.count() ? visibleItems.first() : 0;
+ int firstItemIndex = firstVisible ? firstVisible->index : -1;
+ QList<FxViewItem *> removedBeforeFirstVisible;
+
+ const QVector<QDeclarativeChangeSet::Remove> &removals = currentChanges.pendingChanges.removes();
+ for (int i=0; i<removals.count(); i++) {
+ itemCount -= removals[i].count;
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxViewItem*>::Iterator it = visibleItems.begin();
+ while (it != visibleItems.end()) {
+ FxViewItem *item = *it;
+ if (item->index == -1 || item->index < removals[i].index) {
+ // already removed, or before removed items
+ if (item->index < removals[i].index && !removedVisible)
+ removedVisible = true;
+ ++it;
+ } else if (item->index >= removals[i].index + removals[i].count) {
+ // after removed items
+ item->index -= removals[i].count;
+ ++it;
+ } else {
+ // removed item
+ removedVisible = true;
+ if (!removals[i].isMove())
+ item->attached->emitRemove();
+
+ if (item->attached->delayRemove() && !removals[i].isMove()) {
+ item->index = -1;
+ QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ if (firstVisible && item->position() < firstVisible->position() && item != visibleItems.first())
+ removedBeforeFirstVisible.append(item);
+ if (removals[i].isMove()) {
+ currentChanges.removedItems.insert(removals[i].moveKey(item->index), item);
+ } else {
+ if (item == firstVisible)
+ firstVisible = 0;
+ currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item);
+ }
+ it = visibleItems.erase(it);
+ }
+ }
+ }
+
+ }
+ if (!removals.isEmpty())
+ updateVisibleIndex();
+
+ const QVector<QDeclarativeChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts();
+ bool addedVisible = false;
+ QList<FxViewItem *> addedItems;
+ QList<FxViewItem *> movedBackwards;
+
+ for (int i=0; i<insertions.count(); i++) {
+ bool wasEmpty = visibleItems.isEmpty();
+ if (applyInsertionChange(insertions[i], &movedBackwards, &addedItems, firstVisible))
+ addedVisible = true;
+ if (wasEmpty && !visibleItems.isEmpty())
+ resetFirstItemPosition();
+ itemCount += insertions[i].count;
+ updateVisibleIndex();
+ }
+ for (int i=0; i<addedItems.count(); ++i)
+ addedItems.at(i)->attached->emitAdd();
+
+ // if first visible item is moving but another item is moving up to replace it,
+ // do this positioning now to avoid shifting all content forwards
+ if (firstVisible && firstItemIndex >= 0) {
+ for (int i=0; i<movedBackwards.count(); i++) {
+ if (movedBackwards[i]->index == firstItemIndex) {
+ resetItemPosition(movedBackwards[i], firstVisible);
+ movedBackwards.removeAt(i);
+ break;
+ }
+ }
+ }
+
+ // Ensure we don't cause an ugly list scroll
+ if (firstVisible && visibleItems.count() && visibleItems.first() != firstVisible) {
+ // ensure first item is placed at correct postion if moving backward
+ // since it will be used to position all subsequent items
+ if (movedBackwards.count() && origVisibleItemsFirst)
+ resetItemPosition(visibleItems.first(), origVisibleItemsFirst);
+ moveItemBy(visibleItems.first(), removedBeforeFirstVisible, movedBackwards);
+ }
+
+ // Whatever removed/moved items remain are no longer visible items.
+ for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
+ it != currentChanges.removedItems.end(); ++it) {
+ releaseItem(it.value());
+ }
+ currentChanges.removedItems.clear();
+
+ if (currentChanges.currentChanged) {
+ if (currentChanges.currentRemoved && currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ }
+ if (!currentIndexCleared)
+ updateCurrent(currentChanges.newCurrentIndex);
+ }
+ currentChanges.reset();
+
+ updateSections();
+ if (prevCount != itemCount)
+ emit q->countChanged();
+
+ inApplyModelChanges = false;
+ return removedVisible || addedVisible || !currentChanges.pendingChanges.changes().isEmpty();
+}
+
FxViewItem *QSGItemViewPrivate::createItem(int modelIndex)
{
Q_Q(QSGItemView);
@@ -1415,4 +1694,15 @@ void QSGItemViewPrivate::updateUnrequestedPositions()
repositionPackageItemAt(it.key(), it.value());
}
+void QSGItemViewPrivate::updateVisibleIndex()
+{
+ visibleIndex = 0;
+ for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ visibleIndex = (*it)->index;
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgitemview_p.h b/src/declarative/items/qsgitemview_p.h
index b784015f66..b1093ffdbe 100644
--- a/src/declarative/items/qsgitemview_p.h
+++ b/src/declarative/items/qsgitemview_p.h
@@ -191,13 +191,17 @@ protected:
protected slots:
virtual void updateSections() {}
void destroyRemoved();
- void itemsChanged(int index, int count);
void createdItem(int index, QSGItem *item);
void modelReset();
void destroyingItem(QSGItem *item);
void animStopped();
void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count);
+
private:
Q_DECLARE_PRIVATE(QSGItemView)
};
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
index f20f4cca3e..2164dd60f4 100644
--- a/src/declarative/items/qsgitemview_p_p.h
+++ b/src/declarative/items/qsgitemview_p_p.h
@@ -45,6 +45,7 @@
#include "qsgitemview_p.h"
#include "qsgflickable_p_p.h"
#include "qsgvisualitemmodel_p.h"
+#include <private/qdeclarativechangeset_p.h>
QT_BEGIN_HEADER
@@ -73,6 +74,30 @@ public:
QSGItemViewAttached *attached;
};
+class QSGItemViewChangeSet
+{
+public:
+ QSGItemViewChangeSet();
+
+ bool hasPendingChanges() const;
+ void prepare(int currentIndex, int count);
+ void reset();
+
+ void doInsert(int index, int count);
+ void doRemove(int index, int count);
+ void doMove(int from, int to, int count);
+ void doChange(int index, int count);
+
+ int itemCount;
+ int newCurrentIndex;
+ QDeclarativeChangeSet pendingChanges;
+ QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> removedItems;
+
+ bool active : 1;
+ bool currentChanged : 1;
+ bool currentRemoved : 1;
+};
+
class QSGItemViewPrivate : public QSGFlickablePrivate
{
Q_DECLARE_PUBLIC(QSGItemView)
@@ -92,7 +117,6 @@ public:
FxViewItem *visibleItem(int modelIndex) const;
FxViewItem *firstVisibleItem() const;
int mapFromModel(int modelIndex) const;
- void adjustMoveParameters(int *from, int *to, int *count) const;
virtual void init();
virtual void clear();
@@ -102,7 +126,6 @@ public:
void layout();
void refill();
void refill(qreal from, qreal to, bool doBuffer = false);
- void scheduleLayout();
void mirrorChange();
FxViewItem *createItem(int modelIndex);
@@ -115,7 +138,10 @@ public:
void updateTrackedItem();
void updateUnrequestedIndexes();
void updateUnrequestedPositions();
+ void updateVisibleIndex();
void positionViewAtIndex(int index, int mode);
+ void applyPendingChanges();
+ bool applyModelChanges();
void checkVisible() const;
@@ -135,6 +161,7 @@ public:
FxViewItem *trackedItem;
QHash<QSGItem*,int> unrequestedItems;
int requestedIndex;
+ QSGItemViewChangeSet currentChanges;
// XXX split into struct
QDeclarativeComponent *highlightComponent;
@@ -156,8 +183,9 @@ public:
bool wrap : 1;
bool lazyRelease : 1;
bool deferredRelease : 1;
- bool layoutScheduled : 1;
+ bool inApplyModelChanges : 1;
bool inViewportMoved : 1;
+ bool forceLayout : 1;
bool currentIndexCleared : 1;
bool haveHighlightRange : 1;
bool autoHighlight : 1;
@@ -189,15 +217,19 @@ protected:
virtual void setPosition(qreal pos) = 0;
virtual void fixupPosition() = 0;
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer) = 0;
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo) = 0;
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) = 0;
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
virtual void visibleItemsChanged() = 0;
virtual FxViewItem *newViewItem(int index, QSGItem *item) = 0;
virtual void repositionPackageItemAt(QSGItem *item, int index) = 0;
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem) = 0;
+ virtual void resetFirstItemPosition() = 0;
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &, const QList<FxViewItem *> &) = 0;
virtual void layoutVisibleItems() = 0;
virtual void changedVisibleIndex(int newIndex) = 0;
+ virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *> *, FxViewItem *) = 0;
virtual void initializeViewItem(FxViewItem *) {}
virtual void initializeCurrentItem() {}
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 3be4a4bd58..e8a6bf2d50 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -201,14 +201,17 @@ public:
virtual void init();
virtual void clear();
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
virtual FxViewItem *newViewItem(int index, QSGItem *item);
virtual void initializeViewItem(FxViewItem *item);
virtual void releaseItem(FxViewItem *item);
virtual void repositionPackageItemAt(QSGItem *item, int index);
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
+ virtual void resetFirstItemPosition();
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &items, const QList<FxViewItem *> &movedBackwards);
virtual void createHighlight();
virtual void updateHighlight();
@@ -216,6 +219,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems();
+ bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *> *, FxViewItem *firstVisible);
virtual void updateSections();
void createSection(FxListItemSG *);
@@ -535,7 +539,7 @@ void QSGListViewPrivate::releaseItem(FxViewItem *item)
QSGItemViewPrivate::releaseItem(item);
}
-bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
+bool QSGListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
{
qreal itemEnd = visiblePos;
if (visibleItems.count()) {
@@ -599,7 +603,7 @@ bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer
return changed;
}
-bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+bool QSGListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxViewItem *item = 0;
bool changed = false;
@@ -684,6 +688,27 @@ void QSGListViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
}
}
+void QSGListViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
+{
+ static_cast<FxListItemSG*>(item)->setPosition(toItem->position());
+}
+
+void QSGListViewPrivate::resetFirstItemPosition()
+{
+ FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.first());
+ item->setPosition(0);
+}
+
+void QSGListViewPrivate::moveItemBy(FxViewItem *item, const QList<FxViewItem *> &forwards, const QList<FxViewItem *> &backwards)
+{
+ qreal pos = 0;
+ for (int i=0; i<forwards.count(); i++)
+ pos += forwards[i]->size();
+ for (int i=0; i<backwards.count(); i++)
+ pos -= backwards[i]->size();
+ static_cast<FxListItemSG*>(item)->setPosition(item->position() + pos);
+}
+
void QSGListViewPrivate::createHighlight()
{
Q_Q(QSGListView);
@@ -733,6 +758,8 @@ void QSGListViewPrivate::createHighlight()
void QSGListViewPrivate::updateHighlight()
{
+ applyPendingChanges();
+
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
bool strictHighlight = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
@@ -1009,7 +1036,8 @@ void QSGListViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (item != contentItem && (!highlight || item != highlight->item)) {
if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
- scheduleLayout();
+ forceLayout = true;
+ q->polish();
}
}
}
@@ -1565,6 +1593,7 @@ void QSGListView::setSpacing(qreal spacing)
Q_D(QSGListView);
if (spacing != d->spacing) {
d->spacing = spacing;
+ d->forceLayout = true;
d->layout();
emit spacingChanged();
}
@@ -2067,373 +2096,109 @@ void QSGListView::updateSections()
roles << d->sectionCriteria->property().toUtf8();
d->model->setWatchedRoles(roles);
d->updateSections();
- if (d->itemCount)
+ if (d->itemCount) {
+ d->forceLayout = true;
d->layout();
+ }
}
}
-void QSGListView::itemsInserted(int modelIndex, int count)
+bool QSGListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, QList<FxViewItem *> *movedBackwards, QList<FxViewItem *> *addedItems, FxViewItem *firstVisible)
{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
- d->updateUnrequestedIndexes();
- d->moveReason = QSGListViewPrivate::Other;
+ Q_Q(QSGListView);
+
+ int modelIndex = change.index;
+ int count = change.count;
+
+
+ qreal tempPos = isRightToLeft() ? -position()-size() : position();
+ int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
- qreal tempPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
- int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
if (index < 0) {
- int i = d->visibleItems.count() - 1;
- while (i > 0 && d->visibleItems.at(i)->index == -1)
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
--i;
- if (i == 0 && d->visibleItems.first()->index == -1) {
+ if (i == 0 && visibleItems.first()->index == -1) {
// there are no visible items except items marked for removal
- index = d->visibleItems.count();
- } else if (d->visibleItems.at(i)->index + 1 == modelIndex
- && d->visibleItems.at(i)->endPosition() <= d->buffer+tempPos+d->size()) {
+ index = visibleItems.count();
+ } else if (visibleItems.at(i)->index + 1 == modelIndex
+ && visibleItems.at(i)->endPosition() <= buffer+tempPos+size()) {
// Special case of appending an item to the model.
- index = d->visibleItems.count();
+ index = visibleItems.count();
} else {
- if (modelIndex < d->visibleIndex) {
+ if (modelIndex < visibleIndex) {
// Insert before visible items
- d->visibleIndex += count;
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ visibleIndex += count;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
}
- if (d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem)
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- d->scheduleLayout();
- d->itemCount += count;
- emit countChanged();
- return;
+ return true;
}
}
// index can be the next item past the end of the visible items list (i.e. appended)
int pos = 0;
- if (d->visibleItems.count()) {
- pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
- : d->visibleItems.last()->endPosition()+d->spacing;
+ if (visibleItems.count()) {
+ pos = index < visibleItems.count() ? visibleItems.at(index)->position()
+ : visibleItems.last()->endPosition()+spacing;
}
- int initialPos = pos;
- int diff = 0;
- QList<FxListItemSG*> added;
- bool addedVisible = false;
- FxViewItem *firstVisible = d->firstVisibleItem();
+ int prevAddedCount = addedItems->count();
if (firstVisible && pos < firstVisible->position()) {
// Insert items before the visible item.
int insertionIdx = index;
int i = 0;
- int from = tempPos - d->buffer;
+ int from = tempPos - buffer;
+
for (i = count-1; i >= 0 && pos > from; --i) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(insertionIdx, item);
- pos -= item->size() + d->spacing;
- item->setPosition(pos);
+ if (!item)
+ item = createItem(modelIndex + i);
+
+ visibleItems.insert(insertionIdx, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ pos -= item->size() + spacing;
index++;
}
- if (i >= 0) {
- // If we didn't insert all our new items - anything
- // before the current index is not visible - remove it.
- while (insertionIdx--) {
- FxListItemSG *item = static_cast<FxListItemSG*>(d->visibleItems.takeFirst());
- if (item->index != -1)
- d->visibleIndex++;
- d->releaseItem(item);
- }
- } else {
- // adjust pos of items before inserted items.
- for (int i = insertionIdx-1; i >= 0; i--) {
- FxListItemSG *listItem = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- listItem->setPosition(listItem->position() - (initialPos - pos));
- }
- }
} else {
int i = 0;
- int to = d->buffer+tempPos+d->size();
+ int to = buffer+tempPos+size();
for (i = 0; i < count && pos <= to; ++i) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
- }
- FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(index, item);
- item->setPosition(pos);
- added.append(item);
- pos += item->size() + d->spacing;
- ++index;
- }
- if (i != count) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index)
- d->releaseItem(d->visibleItems.takeLast());
- }
- diff = pos - initialPos;
- }
- if (d->itemCount && d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem) {
- d->currentItem->index = d->currentIndex;
- static_cast<FxListItemSG *>(d->currentItem)->setPosition(static_cast<FxListItemSG *>(d->currentItem)->position() + diff);
- }
- emit currentIndexChanged();
- } else if (!d->itemCount && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
- d->updateCurrent(0);
- }
- // Update the indexes of the following visible items.
- for (; index < d->visibleItems.count(); ++index) {
- FxViewItem *item = d->visibleItems.at(index);
- if (d->currentItem && item->item != d->currentItem->item)
- static_cast<FxListItemSG*>(item)->setPosition(item->position() + diff);
- if (item->index != -1)
- item->index += count;
- }
- // everything is in order now - emit add() signal
- for (int j = 0; j < added.count(); ++j)
- added.at(j)->attached->emitAdd();
-
- d->updateSections();
- d->itemCount += count;
- emit countChanged();
-}
-
-void QSGListView::itemsRemoved(int modelIndex, int count)
-{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
- d->moveReason = QSGListViewPrivate::Other;
- d->updateUnrequestedIndexes();
- d->itemCount -= count;
-
- FxViewItem *firstVisible = d->firstVisibleItem();
- int preRemovedSize = 0;
- bool removedVisible = false;
- // Remove the items from the visible list, skipping anything already marked for removal
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index == -1 || item->index < modelIndex) {
- // already removed, or before removed items
- ++it;
- } else if (item->index >= modelIndex + count) {
- // after removed items
- item->index -= count;
- ++it;
- } else {
- // removed item
- if (!removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- item->attached->emitRemove();
- if (item->attached->delayRemove()) {
- item->index = -1;
- connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
- ++it;
- } else {
- if (item == firstVisible)
- firstVisible = 0;
- if (firstVisible && item->position() < firstVisible->position())
- preRemovedSize += item->size();
- it = d->visibleItems.erase(it);
- d->releaseItem(item);
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- }
- }
+ if (!item)
+ item = createItem(modelIndex + i);
- if (firstVisible && d->visibleItems.first() != firstVisible)
- static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + preRemovedSize);
-
- // update visibleIndex
- bool haveVisibleIndex = false;
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- haveVisibleIndex = true;
- break;
- }
- }
-
- // fix current
- if (d->currentIndex >= modelIndex + count) {
- d->currentIndex -= count;
- if (d->currentItem)
- d->currentItem->index -= count;
- emit currentIndexChanged();
- } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
- // current item has been removed.
- if (d->currentItem) {
- d->currentItem->attached->setIsCurrentItem(false);
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
+ visibleItems.insert(index, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ pos += item->size() + spacing;
+ ++index;
}
- d->currentIndex = -1;
- if (d->itemCount)
- d->updateCurrent(qMin(modelIndex, d->itemCount-1));
- else
- emit currentIndexChanged();
}
- if (!haveVisibleIndex) {
- d->timeline.clear();
- if (removedVisible && d->itemCount == 0) {
- d->visibleIndex = 0;
- d->visiblePos = 0;
- d->setPosition(d->contentStartPosition());
- d->updateHeader();
- d->updateFooter();
- } else {
- if (modelIndex < d->visibleIndex)
- d->visibleIndex = modelIndex+1;
- d->visibleIndex = qMax(qMin(d->visibleIndex, d->itemCount-1), 0);
- }
+ for (; index < visibleItems.count(); ++index) {
+ FxViewItem *item = visibleItems.at(index);
+ if (item->index != -1)
+ item->index += count;
}
- d->updateSections();
- emit countChanged();
+ return addedItems->count() > prevAddedCount;
}
-void QSGListView::itemsMoved(int from, int to, int count)
-{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->isValid())
- return;
- d->updateUnrequestedIndexes();
-
- if (d->visibleItems.isEmpty()) {
- d->refill();
- return;
- }
-
- d->moveReason = QSGListViewPrivate::Other;
-
- bool movingBackwards = from > to;
- d->adjustMoveParameters(&from, &to, &count);
-
- QHash<int,FxViewItem*> moved;
- int moveBy = 0;
- FxViewItem *firstVisible = d->firstVisibleItem();
- int firstItemIndex = firstVisible ? firstVisible->index : -1;
-
- // if visibleItems.first() is above the content start pos, and the items
- // beneath it are moved, ensure this first item is later repositioned correctly
- // (to above the next visible item) so that subsequent layout() is correct
- bool repositionFirstItem = firstVisible
- && d->visibleItems.first()->position() < firstVisible->position()
- && from > d->visibleItems.first()->index;
-
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index >= from && item->index < from + count) {
- // take the items that are moving
- item->index += (to-from);
- moved.insert(item->index, item);
- if (repositionFirstItem)
- moveBy += item->size();
- it = d->visibleItems.erase(it);
- } else {
- // move everything after the moved items.
- if (item->index > from && item->index != -1)
- item->index -= count;
- ++it;
- }
- }
-
- int movedCount = 0;
- int endIndex = d->visibleIndex;
- it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (movedCount < count && item->index >= to && item->index < to + count) {
- // place items in the target position, reusing any existing items
- int targetIndex = item->index + movedCount;
- FxViewItem *movedItem = moved.take(targetIndex);
- if (!movedItem)
- movedItem = d->createItem(targetIndex);
- it = d->visibleItems.insert(it, movedItem);
- ++it;
- ++movedCount;
- } else {
- if (item->index != -1) {
- if (item->index >= to) {
- // update everything after the moved items.
- item->index += count;
- }
- endIndex = item->index;
- }
- ++it;
- }
- }
-
- // If we have moved items to the end of the visible items
- // then add any existing moved items that we have
- while (FxViewItem *item = moved.take(endIndex+1)) {
- d->visibleItems.append(item);
- ++endIndex;
- }
-
- // update visibleIndex
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- // if first visible item is moving but another item is moving up to replace it,
- // do this positioning now to avoid shifting all content forwards
- if (movingBackwards && firstItemIndex >= 0) {
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index == firstItemIndex) {
- static_cast<FxListItemSG*>(*it)->setPosition(firstVisible->position());
- break;
- }
- }
- }
-
- // Fix current index
- if (d->currentIndex >= 0 && d->currentItem) {
- int oldCurrent = d->currentIndex;
- d->currentIndex = d->model->indexOf(d->currentItem->item, this);
- if (oldCurrent != d->currentIndex) {
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- }
-
- // Whatever moved items remain are no longer visible items.
- while (moved.count()) {
- int idx = moved.begin().key();
- FxViewItem *item = moved.take(idx);
- if (d->currentItem && item->item == d->currentItem->item)
- static_cast<FxListItemSG*>(item)->setPosition(d->positionAt(idx));
- d->releaseItem(item);
- }
-
- // Ensure we don't cause an ugly list scroll.
- if (d->visibleItems.count())
- static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
-
- d->updateSections();
- d->layout();
-}
/*!
\qmlmethod QtQuick2::ListView::positionViewAtIndex(int index, PositionMode mode)
diff --git a/src/declarative/items/qsglistview_p.h b/src/declarative/items/qsglistview_p.h
index e45e16b85d..8ff4b05346 100644
--- a/src/declarative/items/qsglistview_p.h
+++ b/src/declarative/items/qsglistview_p.h
@@ -166,11 +166,6 @@ protected:
protected Q_SLOTS:
void updateSections();
-
-private Q_SLOTS:
- void itemsInserted(int index, int count);
- void itemsRemoved(int index, int count);
- void itemsMoved(int from, int to, int count);
};
class QSGListViewAttached : public QSGItemViewAttached
diff --git a/src/declarative/items/qsgshadereffect.cpp b/src/declarative/items/qsgshadereffect.cpp
index 7f7bff7719..f4ad80ea1e 100644
--- a/src/declarative/items/qsgshadereffect.cpp
+++ b/src/declarative/items/qsgshadereffect.cpp
@@ -191,7 +191,7 @@ QSGShaderEffectItem::QSGShaderEffectItem(QSGItem *parent)
QSGShaderEffect::QSGShaderEffect(QSGItem *parent)
: QSGItem(parent)
, m_meshResolution(1, 1)
- , m_deprecatedMesh(0)
+ , m_mesh(0)
, m_cullMode(NoCulling)
, m_blending(true)
, m_dirtyData(true)
@@ -275,63 +275,34 @@ void QSGShaderEffect::setBlending(bool enable)
}
/*!
- \qmlproperty size QtQuick2::ShaderEffect::mesh
+ \qmlproperty variant QtQuick2::ShaderEffect::mesh
- This property holds the mesh resolution. The default resolution is 1x1
- which is the minimum and corresponds to a mesh with four vertices.
- For non-linear vertex transformations, you probably want to set the
- resolution higher.
+ This property defines the mesh used to draw the ShaderEffect. It can hold
+ any mesh object deriving from \l QSGShaderEffectMesh, such as \l GridMesh.
+ If a size value is assigned to this property, the ShaderEffect implicitly
+ uses a \l GridMesh with the value as
+ \l{GridMesh::resolution}{mesh resolution}. By default, this property is
+ the size 1x1.
- \row
- \o \image declarative-gridmesh.png
- \o \qml
- import QtQuick 2.0
-
- ShaderEffect {
- width: 200
- height: 200
- mesh: Qt.size(20, 20)
- property variant source: Image {
- source: "qt-logo.png"
- sourceSize { width: 200; height: 200 }
- smooth: true
- }
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- uniform highp float width;
- void main() {
- highp vec4 pos = qt_Vertex;
- highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
- pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
- }
- \endqml
- \endrow
+ \sa GridMesh
*/
QVariant QSGShaderEffect::mesh() const
{
- return m_deprecatedMesh ? qVariantFromValue(static_cast<QObject *>(m_deprecatedMesh))
- : qVariantFromValue(m_meshResolution);
+ return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
+ : qVariantFromValue(m_meshResolution);
}
void QSGShaderEffect::setMesh(const QVariant &mesh)
{
- // TODO: Replace QVariant with QSize after grace period.
QSGShaderEffectMesh *newMesh = qobject_cast<QSGShaderEffectMesh *>(qVariantValue<QObject *>(mesh));
- if (newMesh && newMesh == m_deprecatedMesh)
+ if (newMesh && newMesh == m_mesh)
return;
- if (m_deprecatedMesh)
- disconnect(m_deprecatedMesh, SIGNAL(geometryChanged()), this, 0);
- m_deprecatedMesh = newMesh;
- if (m_deprecatedMesh) {
- qWarning("ShaderEffect: Setting the mesh to something other than a size is deprecated.");
- connect(m_deprecatedMesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
+ if (m_mesh)
+ disconnect(m_mesh, SIGNAL(geometryChanged()), this, 0);
+ m_mesh = newMesh;
+ if (m_mesh) {
+ connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
} else {
if (qVariantCanConvert<QSize>(mesh)) {
m_meshResolution = mesh.toSize();
@@ -347,7 +318,7 @@ void QSGShaderEffect::setMesh(const QVariant &mesh)
}
}
if (!ok)
- qWarning("ShaderEffect: mesh resolution must be a size.");
+ qWarning("ShaderEffect: mesh property must be size or object deriving from QSGShaderEffectMesh.");
}
m_defaultMesh.setResolution(m_meshResolution);
}
@@ -511,10 +482,9 @@ void QSGShaderEffect::updateProperties()
lookThroughShaderCode(vertexCode);
lookThroughShaderCode(fragmentCode);
- // TODO: Remove !m_deprecatedMesh check after grace period.
- if (!m_deprecatedMesh && !m_source.attributeNames.contains(qt_position_attribute_name))
+ if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name))
qWarning("QSGShaderEffect: Missing reference to \'%s\'.", qt_position_attribute_name);
- if (!m_deprecatedMesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
+ if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
qWarning("QSGShaderEffect: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
if (!m_source.respectsMatrix)
qWarning("QSGShaderEffect: Missing reference to \'qt_Matrix\'.");
@@ -608,7 +578,7 @@ QSGNode *QSGShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node->setFlag(QSGNode::OwnsGeometry, false);
QSGGeometry *geometry = node->geometry();
QRectF rect(0, 0, width(), height());
- QSGShaderEffectMesh *mesh = m_deprecatedMesh ? m_deprecatedMesh : &m_defaultMesh;
+ QSGShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
if (!geometry) {
diff --git a/src/declarative/items/qsgshadereffect_p.h b/src/declarative/items/qsgshadereffect_p.h
index 5d90fe0e61..a8c3f084e4 100644
--- a/src/declarative/items/qsgshadereffect_p.h
+++ b/src/declarative/items/qsgshadereffect_p.h
@@ -131,7 +131,7 @@ private:
QSGShaderEffectProgram m_source;
QSize m_meshResolution;
- QSGShaderEffectMesh *m_deprecatedMesh; // TODO: Remove after grace period.
+ QSGShaderEffectMesh *m_mesh;
QSGGridMesh m_defaultMesh;
CullMode m_cullMode;
diff --git a/src/declarative/items/qsgshadereffectmesh.cpp b/src/declarative/items/qsgshadereffectmesh.cpp
index 6d3d17e4ff..53fd917e06 100644
--- a/src/declarative/items/qsgshadereffectmesh.cpp
+++ b/src/declarative/items/qsgshadereffectmesh.cpp
@@ -51,8 +51,9 @@ QSGShaderEffectMesh::QSGShaderEffectMesh(QObject *parent)
}
/*!
- \class QSGGridMesh
- \since 5.0
+ \qmlclass GridMesh QSGGridMesh
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
\brief GridMesh defines a mesh with vertices arranged in a grid.
GridMesh defines a rectangular mesh consisting of vertices arranged in an
@@ -152,12 +153,47 @@ QSGGeometry *QSGGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QB
}
/*!
- \property QSGGridMesh::resolution
+ \qmlproperty size QtQuick2::GridMesh::resolution
This property holds the grid resolution. The resolution's width and height
specify the number of cells or spacings between vertices horizontally and
vertically respectively. The minimum and default is 1x1, which corresponds
to four vertices in total, one in each corner.
+ For non-linear vertex transformations, you probably want to set the
+ resolution higher.
+
+ \row
+ \o \image declarative-gridmesh.png
+ \o \qml
+ import QtQuick 2.0
+
+ ShaderEffect {
+ width: 200
+ height: 200
+ mesh: GridMesh {
+ resolution: Qt.size(20, 20)
+ }
+ property variant source: Image {
+ source: "qt-logo.png"
+ sourceSize { width: 200; height: 200 }
+ smooth: true
+ }
+ vertexShader: "
+ uniform highp mat4 qt_Matrix;
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec2 qt_MultiTexCoord0;
+ varying highp vec2 qt_TexCoord0;
+ uniform highp float width;
+ void main() {
+ highp vec4 pos = qt_Vertex;
+ highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
+ pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
+ gl_Position = qt_Matrix * pos;
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ }"
+ }
+ \endqml
+ \endrow
*/
void QSGGridMesh::setResolution(const QSize &res)
diff --git a/src/declarative/items/qsgshadereffectmesh_p.h b/src/declarative/items/qsgshadereffectmesh_p.h
index 4a1a8ae61b..428674fdba 100644
--- a/src/declarative/items/qsgshadereffectmesh_p.h
+++ b/src/declarative/items/qsgshadereffectmesh_p.h
@@ -59,7 +59,7 @@ QT_MODULE(Declarative)
class QSGGeometry;
class QRectF;
-class QSGShaderEffectMesh : public QObject
+class Q_DECLARATIVE_EXPORT QSGShaderEffectMesh : public QObject
{
Q_OBJECT
public:
diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp
index a00a217ee3..f936c3f32b 100644
--- a/src/declarative/items/qsgtext.cpp
+++ b/src/declarative/items/qsgtext.cpp
@@ -1328,10 +1328,15 @@ void QSGText::resetMaximumLineCount()
styling markup, in the style of html 3.2:
\code
- <font size="4" color="#ff0000">font size and color</font>
- <b>bold</b>
- <i>italic</i>
- <br>
+ <b></b> - bold
+ <i></i> - italic
+ <br> - new line
+ <p> - paragraph
+ <u> - underlined text
+ <font color="color_name" size="1-7"></font>
+ <h1> to <h6> - headers
+ <a href=""> - anchor
+ <ol type="">, <ul type=""> and <li> - ordered and unordered lists
&gt; &lt; &amp;
\endcode
diff --git a/src/declarative/items/qsgtextedit.cpp b/src/declarative/items/qsgtextedit.cpp
index 1afb36f035..885fdaf395 100644
--- a/src/declarative/items/qsgtextedit.cpp
+++ b/src/declarative/items/qsgtextedit.cpp
@@ -1675,6 +1675,7 @@ void QSGTextEdit::q_textChanged()
void QSGTextEdit::moveCursorDelegate()
{
Q_D(QSGTextEdit);
+ d->determineHorizontalAlignment();
updateMicroFocus();
emit cursorRectangleChanged();
if(!d->cursor)
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 42105cf9ce..ab6be666d8 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -403,6 +403,8 @@ bool QSGTextInputPrivate::determineHorizontalAlignment()
if (hAlignImplicit) {
// if no explicit alignment has been set, follow the natural layout direction of the text
QString text = control->text();
+ if (text.isEmpty())
+ text = control->preeditAreaText();
bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
return setHAlign(isRightToLeft ? QSGTextInput::AlignRight : QSGTextInput::AlignLeft);
}
@@ -1900,6 +1902,7 @@ void QSGTextInput::cursorPosChanged()
void QSGTextInput::updateCursorRectangle()
{
Q_D(QSGTextInput);
+ d->determineHorizontalAlignment();
d->updateHorizontalScroll();
updateRect();//TODO: Only update rect between pos's
updateMicroFocus();
diff --git a/src/declarative/items/qsgview.h b/src/declarative/items/qsgview.h
index 62b52c865b..2d8e8b4067 100644
--- a/src/declarative/items/qsgview.h
+++ b/src/declarative/items/qsgview.h
@@ -43,8 +43,9 @@
#ifndef QSGVIEW_H
#define QSGVIEW_H
-#include <QtCore/qurl.h>
#include <qsgcanvas.h>
+#include <QtCore/qurl.h>
+#include <QtDeclarative/qdeclarativedebug.h>
QT_BEGIN_HEADER
diff --git a/src/declarative/particles/particles.pri b/src/declarative/particles/particles.pri
index 9f63cd81b9..527bd9ae61 100644
--- a/src/declarative/particles/particles.pri
+++ b/src/declarative/particles/particles.pri
@@ -1,18 +1,18 @@
INCLUDEPATH += $$PWD
HEADERS += \
- $$PWD/qsgangleddirection_p.h \
+ $$PWD/qsgangledirection_p.h \
$$PWD/qsgcustomparticle_p.h \
+ $$PWD/qsgcustomaffector_p.h \
$$PWD/qsgellipseextruder_p.h \
- $$PWD/qsgfollowemitter_p.h \
+ $$PWD/qsgtrailemitter_p.h \
$$PWD/qsgfriction_p.h \
$$PWD/qsggravity_p.h \
$$PWD/qsgimageparticle_p.h \
$$PWD/qsgitemparticle_p.h \
- $$PWD/qsgkill_p.h \
+ $$PWD/qsgage_p.h \
$$PWD/qsglineextruder_p.h \
$$PWD/qsgmaskextruder_p.h \
- $$PWD/qsgmodelparticle_p.h \
$$PWD/qsgparticleaffector_p.h \
$$PWD/qsgparticleemitter_p.h \
$$PWD/qsgparticleextruder_p.h \
@@ -22,27 +22,28 @@ HEADERS += \
$$PWD/qsgpointattractor_p.h \
$$PWD/qsgpointdirection_p.h \
$$PWD/qsgspritegoal_p.h \
- $$PWD/qsgstochasticdirection_p.h \
- $$PWD/qsgtargeteddirection_p.h \
+ $$PWD/qsgdirection_p.h \
+ $$PWD/qsgtargetdirection_p.h \
$$PWD/qsgturbulence_p.h \
$$PWD/qsgwander_p.h \
$$PWD/qsgtargetaffector_p.h \
$$PWD/qsgcumulativedirection_p.h \
- $$PWD/qsgv8particledata_p.h
+ $$PWD/qsgv8particledata_p.h \
+ $$PWD/qsgrectangleextruder_p.h
SOURCES += \
- $$PWD/qsgangleddirection.cpp \
+ $$PWD/qsgangledirection.cpp \
$$PWD/qsgcustomparticle.cpp \
+ $$PWD/qsgcustomaffector.cpp \
$$PWD/qsgellipseextruder.cpp \
- $$PWD/qsgfollowemitter.cpp \
+ $$PWD/qsgtrailemitter.cpp \
$$PWD/qsgfriction.cpp \
$$PWD/qsggravity.cpp \
$$PWD/qsgimageparticle.cpp \
$$PWD/qsgitemparticle.cpp \
- $$PWD/qsgkill.cpp \
+ $$PWD/qsgage.cpp \
$$PWD/qsglineextruder.cpp \
$$PWD/qsgmaskextruder.cpp \
- $$PWD/qsgmodelparticle.cpp \
$$PWD/qsgparticleaffector.cpp \
$$PWD/qsgparticleemitter.cpp \
$$PWD/qsgparticleextruder.cpp \
@@ -52,13 +53,14 @@ SOURCES += \
$$PWD/qsgpointattractor.cpp \
$$PWD/qsgpointdirection.cpp \
$$PWD/qsgspritegoal.cpp \
- $$PWD/qsgstochasticdirection.cpp \
- $$PWD/qsgtargeteddirection.cpp \
+ $$PWD/qsgdirection.cpp \
+ $$PWD/qsgtargetdirection.cpp \
$$PWD/qsgturbulence.cpp \
$$PWD/qsgwander.cpp \
$$PWD/qsgtargetaffector.cpp \
$$PWD/qsgcumulativedirection.cpp \
- $$PWD/qsgv8particledata.cpp
+ $$PWD/qsgv8particledata.cpp \
+ $$PWD/qsgrectangleextruder.cpp
RESOURCES += \
$$PWD/particles.qrc
diff --git a/src/declarative/particles/qsgage.cpp b/src/declarative/particles/qsgage.cpp
new file mode 100644
index 0000000000..2c0678fd0e
--- /dev/null
+++ b/src/declarative/particles/qsgage.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qsgage_p.h"
+#include "qsgparticleemitter_p.h"
+QT_BEGIN_NAMESPACE
+/*!
+ \qmlclass Age QSGAgeAffector
+ \inqmlmodule QtQuick.Particles 2
+ \inherits Affector
+ \brief The Age affector allows you to prematurely age particles
+
+ The Age affector allows you to alter where the particle is in its lifecycle. Common uses
+ are to expire particles prematurely, possibly giving them time to animate out.
+
+ The Age affector only applies to particles which are still alive.
+*/
+/*!
+ \qmlproperty int QtQuick.Particles2::Age::lifeLeft
+
+ The amount of life to set the particle to have. Affected particles
+ will jump to a point in their life where they will have this many
+ milliseconds left to live.
+*/
+
+QSGAgeAffector::QSGAgeAffector(QSGItem *parent) :
+ QSGParticleAffector(parent), m_lifeLeft(0)
+{
+}
+
+
+bool QSGAgeAffector::affectParticle(QSGParticleData *d, qreal dt)
+{
+ Q_UNUSED(dt);
+ if (d->stillAlive()){
+ qreal curT = (qreal)m_system->m_timeInt/1000.0;
+ qreal ttl = (qreal)m_lifeLeft/1000.0;
+ d->t = curT - (d->lifeSpan - ttl) + 1;
+ return true;
+ }
+ return false;
+}
+QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgage_p.h b/src/declarative/particles/qsgage_p.h
new file mode 100644
index 0000000000..c4c9929ad8
--- /dev/null
+++ b/src/declarative/particles/qsgage_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 KILLAFFECTOR_H
+#define KILLAFFECTOR_H
+#include "qsgparticleaffector_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+class QSGAgeAffector : public QSGParticleAffector
+{
+ Q_OBJECT
+ Q_PROPERTY(int lifeLeft READ lifeLeft WRITE setLifeLeft NOTIFY lifeLeftChanged)
+
+public:
+ explicit QSGAgeAffector(QSGItem *parent = 0);
+
+ int lifeLeft() const
+ {
+ return m_lifeLeft;
+ }
+
+protected:
+ virtual bool affectParticle(QSGParticleData *d, qreal dt);
+signals:
+ void lifeLeftChanged(int arg);
+
+public slots:
+ void setLifeLeft(int arg)
+ {
+ if (m_lifeLeft != arg) {
+ m_lifeLeft = arg;
+ emit lifeLeftChanged(arg);
+ }
+ }
+
+private:
+
+int m_lifeLeft;
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // KILLAFFECTOR_H
diff --git a/src/declarative/particles/qsgangleddirection.cpp b/src/declarative/particles/qsgangledirection.cpp
index 844941c178..10a31bf07e 100644
--- a/src/declarative/particles/qsgangleddirection.cpp
+++ b/src/declarative/particles/qsgangledirection.cpp
@@ -39,21 +39,21 @@
**
****************************************************************************/
-#include "qsgangleddirection_p.h"
+#include "qsgangledirection_p.h"
#include <cmath>
QT_BEGIN_NAMESPACE
const qreal CONV = 0.017453292519943295;
/*!
- \qmlclass AngledDirection QSGAngledDirection
+ \qmlclass AngleDirection QSGAngleDirection
\inqmlmodule QtQuick.Particles 2
- \inherits StochasticDirection
- \brief The AngledDirection element allows you to specify a direction that varies in angle
+ \inherits Direction
+ \brief The AngleDirection element allows you to specify a direction that varies in angle
The AngledDirection element allows both the specification of a direction by angle and magnitude,
as well as varying the parameters by angle or magnitude.
*/
/*!
- \qmlproperty real QtQuick.Particles2::AngledDirection::angle
+ \qmlproperty real QtQuick.Particles2::AngleDirection::angle
This property specifies the base angle for the direction.
The angle of this direction will vary by no more than angleVariation
from this angle.
@@ -63,7 +63,7 @@ const qreal CONV = 0.017453292519943295;
The default value is zero.
*/
/*!
- \qmlproperty real QtQuick.Particles2::AngledDirection::magnitude
+ \qmlproperty real QtQuick.Particles2::AngleDirection::magnitude
This property specifies the base magnitude for the direction.
The magnitude of this direction will vary by no more than magnitudeVariation
from this magnitude.
@@ -73,7 +73,7 @@ const qreal CONV = 0.017453292519943295;
The default value is zero.
*/
/*!
- \qmlproperty real QtQuick.Particles2::AngledDirection::angleVariation
+ \qmlproperty real QtQuick.Particles2::AngleDirection::angleVariation
This property specifies the maximum angle variation for the direction.
The angle of the direction will vary by up to angleVariation clockwise
and anticlockwise from the value specified in angle.
@@ -83,7 +83,7 @@ const qreal CONV = 0.017453292519943295;
The default value is zero.
*/
/*!
- \qmlproperty real QtQuick.Particles2::AngledDirection::magnitudeVariation
+ \qmlproperty real QtQuick.Particles2::AngleDirection::magnitudeVariation
This property specifies the base magnitude for the direction.
The magnitude of this direction will vary by no more than magnitudeVariation
from the base magnitude.
@@ -92,8 +92,8 @@ const qreal CONV = 0.017453292519943295;
The default value is zero.
*/
-QSGAngledDirection::QSGAngledDirection(QObject *parent) :
- QSGStochasticDirection(parent)
+QSGAngleDirection::QSGAngleDirection(QObject *parent) :
+ QSGDirection(parent)
, m_angle(0)
, m_magnitude(0)
, m_angleVariation(0)
@@ -102,7 +102,7 @@ QSGAngledDirection::QSGAngledDirection(QObject *parent) :
}
-const QPointF &QSGAngledDirection::sample(const QPointF &)
+const QPointF &QSGAngleDirection::sample(const QPointF &from)
{
//TODO: Faster
qreal theta = m_angle*CONV - m_angleVariation*CONV + rand()/float(RAND_MAX) * m_angleVariation*CONV * 2;
diff --git a/src/declarative/particles/qsgangleddirection_p.h b/src/declarative/particles/qsgangledirection_p.h
index 4d5522d13c..870a7eb0d9 100644
--- a/src/declarative/particles/qsgangleddirection_p.h
+++ b/src/declarative/particles/qsgangledirection_p.h
@@ -41,14 +41,14 @@
#ifndef QSGANGLEDDIRECTION_H
#define QSGANGLEDDIRECTION_H
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGAngledDirection : public QSGStochasticDirection
+class QSGAngleDirection : public QSGDirection
{
Q_OBJECT
Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
@@ -56,7 +56,7 @@ class QSGAngledDirection : public QSGStochasticDirection
Q_PROPERTY(qreal angleVariation READ angleVariation WRITE setAngleVariation NOTIFY angleVariationChanged)
Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
public:
- explicit QSGAngledDirection(QObject *parent = 0);
+ explicit QSGAngleDirection(QObject *parent = 0);
const QPointF &sample(const QPointF &from);
qreal angle() const
{
diff --git a/src/declarative/particles/qsgcumulativedirection.cpp b/src/declarative/particles/qsgcumulativedirection.cpp
index 3502b41bce..8e4e6b681d 100644
--- a/src/declarative/particles/qsgcumulativedirection.cpp
+++ b/src/declarative/particles/qsgcumulativedirection.cpp
@@ -45,26 +45,26 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass CumulativeDirection QSGCumulativeDirection
\inqmlmodule QtQuick.Particles 2
- \inherits StochasticDirection
+ \inherits Direction
\brief The CumulativeDirection element allows you to specify a direction made of other directions
The CumulativeDirection element will act as a direction that sums the directions within it.
*/
-QSGCumulativeDirection::QSGCumulativeDirection(QObject *parent):QSGStochasticDirection(parent)
+QSGCumulativeDirection::QSGCumulativeDirection(QObject *parent):QSGDirection(parent)
{
}
-QDeclarativeListProperty<QSGStochasticDirection> QSGCumulativeDirection::directions()
+QDeclarativeListProperty<QSGDirection> QSGCumulativeDirection::directions()
{
- return QDeclarativeListProperty<QSGStochasticDirection>(this, m_directions);//TODO: Proper list property
+ return QDeclarativeListProperty<QSGDirection>(this, m_directions);//TODO: Proper list property
}
const QPointF &QSGCumulativeDirection::sample(const QPointF &from)
{
- m_ret = QPointF();
- foreach (QSGStochasticDirection* dir, m_directions)
- m_ret += dir->sample(from);
- return m_ret;
+ QPointF ret;
+ foreach (QSGDirection* dir, m_directions)
+ ret += dir->sample(from);
+ return ret;
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgcumulativedirection_p.h b/src/declarative/particles/qsgcumulativedirection_p.h
index 53ed7613a1..4f93fed1bd 100644
--- a/src/declarative/particles/qsgcumulativedirection_p.h
+++ b/src/declarative/particles/qsgcumulativedirection_p.h
@@ -41,7 +41,7 @@
#ifndef QSGCUMULATIVEDIRECTION_P_H
#define QSGCUMULATIVEDIRECTION_P_H
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
#include <QDeclarativeListProperty>
QT_BEGIN_HEADER
@@ -49,17 +49,16 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGCumulativeDirection : public QSGStochasticDirection
+class QSGCumulativeDirection : public QSGDirection
{
Q_OBJECT
- Q_PROPERTY(QDeclarativeListProperty<QSGStochasticDirection> directions READ directions)
+ Q_PROPERTY(QDeclarativeListProperty<QSGDirection> directions READ directions)
Q_CLASSINFO("DefaultProperty", "directions")
public:
explicit QSGCumulativeDirection(QObject *parent = 0);
- QDeclarativeListProperty<QSGStochasticDirection> directions();
+ QDeclarativeListProperty<QSGDirection> directions();
const QPointF &sample(const QPointF &from);
private:
- QList<QSGStochasticDirection*> m_directions;
- QPointF m_ret;
+ QList<QSGDirection*> m_directions;
};
#endif // QSGCUMULATIVEDIRECTION_P_H
diff --git a/src/declarative/particles/qsgcustomaffector.cpp b/src/declarative/particles/qsgcustomaffector.cpp
new file mode 100644
index 0000000000..70e1dbe035
--- /dev/null
+++ b/src/declarative/particles/qsgcustomaffector.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qsgcustomaffector_p.h"
+#include <QDebug>
+QT_BEGIN_NAMESPACE
+
+//TODO: Move docs (and inherit) to real base when docs can propagate
+//TODO: Document particle 'type'
+/*!
+ \qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
+
+ This handler is called when particles are selected to be affected.
+
+ dt is the time since the last time it was affected. Use dt to normalize
+ trajectory manipulations to real time.
+
+ Note that JS is slower to execute, so it is not recommended to use this in
+ high-volume particle systems.
+*/
+QSGCustomAffector::QSGCustomAffector(QSGItem *parent) :
+ QSGParticleAffector(parent)
+{
+}
+
+bool QSGCustomAffector::isAffectConnected()
+{
+ static int idx = QObjectPrivate::get(this)->signalIndex("affectParticle(QDeclarativeV8Handle,qreal)");
+ return QObjectPrivate::get(this)->isSignalConnected(idx);
+}
+
+bool QSGCustomAffector::affectParticle(QSGParticleData *d, qreal dt)
+{
+ if (isAffectConnected()){
+ d->update = 0.0;
+ emit affectParticle(d->v8Value(), dt);
+ return d->update == 1.0;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgkill_p.h b/src/declarative/particles/qsgcustomaffector_p.h
index d1e2292f13..7f39200298 100644
--- a/src/declarative/particles/qsgkill_p.h
+++ b/src/declarative/particles/qsgcustomaffector_p.h
@@ -39,8 +39,12 @@
**
****************************************************************************/
-#ifndef KILLAFFECTOR_H
-#define KILLAFFECTOR_H
+#ifndef CUSTOMAFFECTOR_H
+#define CUSTOMAFFECTOR_H
+
+#include <QObject>
+#include "qsgparticlesystem_p.h"
+#include "qsgparticleextruder_p.h"
#include "qsgparticleaffector_p.h"
QT_BEGIN_HEADER
@@ -49,20 +53,22 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-
-class QSGKillAffector : public QSGParticleAffector
+class QSGCustomAffector : public QSGParticleAffector
{
Q_OBJECT
+
public:
- explicit QSGKillAffector(QSGItem *parent = 0);
-protected:
- virtual bool affectParticle(QSGParticleData *d, qreal dt);
-signals:
+ explicit QSGCustomAffector(QSGItem *parent = 0);
+signals:
+ void affectParticle(QDeclarativeV8Handle particle, qreal dt);
public slots:
-
+protected:
+ bool isAffectConnected();
+ virtual bool affectParticle(QSGParticleData *d, qreal dt);
+private:
};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // KILLAFFECTOR_H
+#endif // CUSTOMAFFECTOR_H
diff --git a/src/declarative/particles/qsgcustomparticle.cpp b/src/declarative/particles/qsgcustomparticle.cpp
index eb6f45e2f0..e1999f2bee 100644
--- a/src/declarative/particles/qsgcustomparticle.cpp
+++ b/src/declarative/particles/qsgcustomparticle.cpp
@@ -47,36 +47,36 @@ QT_BEGIN_NAMESPACE
//Includes comments because the code isn't self explanatory
static const char qt_particles_template_vertex_code[] =
- "attribute highp vec2 vPos; \n"
- "attribute highp vec2 vTex; \n"
- "attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize \n"
- "attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration \n"
- "attribute highp float r; \n"
- "uniform highp mat4 qt_Matrix; \n"
- "uniform highp float timestamp; \n"
- "varying highp vec2 fTex; \n"
- "void defaultMain() { \n"
- " fTex = vTex; \n"
- " highp float size = vData.z; \n"
- " highp float endSize = vData.w; \n"
- " highp float t = (timestamp - vData.x) / vData.y; \n"
- " highp float currentSize = mix(size, endSize, t * t); \n"
- " if (t < 0. || t > 1.) \n"
- " currentSize = 0.; \n"
- " highp vec2 pos = vPos \n"
- " - currentSize / 2. + currentSize * vTex // adjust size \n"
- " + vVec.xy * t * vData.y // apply speed vector.. \n"
- " + 0.5 * vVec.zw * pow(t * vData.y, 2.); \n"
- " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); \n"
- "}\n";
+ "attribute highp vec2 qt_ParticlePos;\n"
+ "attribute highp vec2 qt_ParticleTex;\n"
+ "attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize\n"
+ "attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration\n"
+ "attribute highp float qt_ParticleR;\n"
+ "uniform highp mat4 qt_Matrix;\n"
+ "uniform highp float qt_Timestamp;\n"
+ "varying highp vec2 qt_TexCoord0;\n"
+ "void defaultMain() {\n"
+ " qt_TexCoord0 = qt_ParticleTex;\n"
+ " highp float size = qt_ParticleData.z;\n"
+ " highp float endSize = qt_ParticleData.w;\n"
+ " highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;\n"
+ " highp float currentSize = mix(size, endSize, t * t);\n"
+ " if (t < 0. || t > 1.)\n"
+ " currentSize = 0.;\n"
+ " highp vec2 pos = qt_ParticlePos\n"
+ " - currentSize / 2. + currentSize * qt_ParticleTex // adjust size\n"
+ " + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..\n"
+ " + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);\n"
+ " gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);\n"
+ "}";
static const char qt_particles_default_vertex_code[] =
"void main() { \n"
" defaultMain(); \n"
"}";
-static const char qt_particles_default_fragment_code[] =//TODO: Default frag requires source?
+static const char qt_particles_default_fragment_code[] =
"uniform sampler2D source; \n"
- "varying highp vec2 fTex; \n"
+ "varying highp vec2 qt_TexCoord0; \n"
"uniform lowp float qt_Opacity; \n"
"void main() { \n"
" gl_FragColor = texture2D(source, fTex) * qt_Opacity; \n"
@@ -159,7 +159,7 @@ void QSGCustomParticle::componentComplete()
This property holds the fragment shader's GLSL source code.
The default shader expects the texture coordinate to be passed from the
- vertex shader as "varying highp vec2 fTex", and it samples from a
+ vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
sampler2D named "source".
*/
@@ -180,31 +180,31 @@ void QSGCustomParticle::setFragmentShader(const QByteArray &code)
This property holds the vertex shader's GLSL source code.
The default shader passes the texture coordinate along to the fragment
- shader as "varying highp vec2 fTex".
+ shader as "varying highp vec2 qt_TexCoord0".
To aid writing a particle vertex shader, the following GLSL code is prepended
to your vertex shader:
\code
- attribute highp vec2 vPos;
- attribute highp vec2 vTex;
- attribute highp vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
- attribute highp vec4 vVec; // x,y = constant speed, z,w = acceleration
- attribute highp float r;
+ attribute highp vec2 qt_ParticlePos;
+ attribute highp vec2 qt_ParticleTex;
+ attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
+ attribute highp vec4 qt_ParticleVec; // x,y = constant speed, z,w = acceleration
+ attribute highp float qt_ParticleR;
uniform highp mat4 qt_Matrix;
- uniform highp float timestamp;
- varying highp vec2 fTex;
+ uniform highp float qt_Timestamp;
+ varying highp vec2 qt_TexCoord0;
void defaultMain() {
- fTex = vTex;
- highp float size = vData.z;
- highp float endSize = vData.w;
- highp float t = (timestamp - vData.x) / vData.y;
+ qt_TexCoord0 = qt_ParticleTex;
+ highp float size = qt_ParticleData.z;
+ highp float endSize = qt_ParticleData.w;
+ highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
highp float currentSize = mix(size, endSize, t * t);
if (t < 0. || t > 1.)
currentSize = 0.;
- highp vec2 pos = vPos
- - currentSize / 2. + currentSize * vTex // adjust size
- + vVec.xy * t * vData.y // apply speed vector..
- + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ highp vec2 pos = qt_ParticlePos
+ - currentSize / 2. + currentSize * qt_ParticleTex // adjust size
+ + qt_ParticleVec.xy * t * qt_ParticleData.y // apply speed vector..
+ + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
}
\endcode
@@ -348,7 +348,11 @@ void QSGCustomParticle::updateProperties()
vertexCode = qt_particles_template_vertex_code + vertexCode;
m_source.attributeNames.clear();
- m_source.attributeNames << "vPos" << "vTex" << "vData" << "vVec" << "r";
+ m_source.attributeNames << "qt_ParticlePos"
+ << "qt_ParticleTex"
+ << "qt_ParticleData"
+ << "qt_ParticleVec"
+ << "qt_ParticleR";
lookThroughShaderCode(vertexCode);
lookThroughShaderCode(fragmentCode);
@@ -392,8 +396,8 @@ void QSGCustomParticle::lookThroughShaderCode(const QByteArray &code)
m_source.respectsMatrix = true;
} else if (name == "qt_Opacity") {
m_source.respectsOpacity = true;
- } else if (name == "timestamp") {
- //TODO: Copy the whole thing just because I have one more uniform?
+ } else if (name == "qt_Timestamp") {
+ //Not strictly necessary
} else {
m_source.uniformNames.insert(name);
if (type == "sampler2D") {
@@ -421,13 +425,14 @@ QSGNode *QSGCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
m_dirtyData = false;
}
- if (m_system && m_system->isRunning())
+ if (m_system && m_system->isRunning() && !m_system->isPaused()){
prepareNextFrame();
- if (m_rootNode){
- update();
- //### Should I be using dirty geometry too/instead?
- foreach (QSGShaderEffectNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyMaterial); //done in buildData?
+ if (m_rootNode) {
+ update();
+ //### Should I be using dirty geometry too/instead?
+ foreach (QSGGeometryNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyMaterial);//done in buildData?
+ }
}
return m_rootNode;
@@ -526,12 +531,12 @@ QSGShaderEffectNode* QSGCustomParticle::buildCustomNodes()
return *(m_nodes.begin());
}
-static const QByteArray timestampName("timestamp");
void QSGCustomParticle::buildData()
{
if (!m_rootNode)
return;
+ const QByteArray timestampName("qt_Timestamp");
QVector<QPair<QByteArray, QVariant> > values;
QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material->textureProviders();
diff --git a/src/declarative/particles/qsgstochasticdirection.cpp b/src/declarative/particles/qsgdirection.cpp
index cdbc9f15ad..f233a56f61 100644
--- a/src/declarative/particles/qsgstochasticdirection.cpp
+++ b/src/declarative/particles/qsgdirection.cpp
@@ -39,23 +39,23 @@
**
****************************************************************************/
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
QT_BEGIN_NAMESPACE
/*!
- \qmlclass StochasticDirection QSGStochasticDirection
+ \qmlclass Direction QSGDirection
\inqmlmodule QtQuick.Particles 2
- \brief The StochasticDirection elements allow you to specify a vector space.
+ \brief The Direction elements allow you to specify a vector space.
*/
-QSGStochasticDirection::QSGStochasticDirection(QObject *parent) :
+QSGDirection::QSGDirection(QObject *parent) :
QObject(parent)
{
}
-const QPointF &QSGStochasticDirection::sample(const QPointF &from)
+const QPointF &QSGDirection::sample(const QPointF &from)
{
return m_ret;
}
diff --git a/src/declarative/particles/qsgstochasticdirection_p.h b/src/declarative/particles/qsgdirection_p.h
index 764937fc00..f64d5644e7 100644
--- a/src/declarative/particles/qsgstochasticdirection_p.h
+++ b/src/declarative/particles/qsgdirection_p.h
@@ -52,11 +52,11 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGStochasticDirection : public QObject
+class QSGDirection : public QObject
{
Q_OBJECT
public:
- explicit QSGStochasticDirection(QObject *parent = 0);
+ explicit QSGDirection(QObject *parent = 0);
virtual const QPointF &sample(const QPointF &from);
signals:
diff --git a/src/declarative/particles/qsgfriction.cpp b/src/declarative/particles/qsgfriction.cpp
index 6baeaf6c3b..031fc896bf 100644
--- a/src/declarative/particles/qsgfriction.cpp
+++ b/src/declarative/particles/qsgfriction.cpp
@@ -51,6 +51,8 @@ QT_BEGIN_NAMESPACE
/*!
\qmlproperty real QtQuick.Particles2::Friction::factor
+
+ A drag will be applied to moving objects which is this factor of their current velocity.
*/
QSGFrictionAffector::QSGFrictionAffector(QSGItem *parent) :
diff --git a/src/declarative/particles/qsggravity.cpp b/src/declarative/particles/qsggravity.cpp
index 1de2a0e014..d775b49d6f 100644
--- a/src/declarative/particles/qsggravity.cpp
+++ b/src/declarative/particles/qsggravity.cpp
@@ -51,14 +51,22 @@ const qreal CONV = 0.017453292520444443;
This element will set the acceleration of all affected particles to a vector of
the specified magnitude in the specified angle.
+
+ This element models the gravity of a massive object whose center of
+ gravity is far away (and thus the gravitational pull is effectively constant
+ across the scene). To model the gravity of an object near or inside the scene,
+ use PointAttractor.
*/
/*!
\qmlproperty real QtQuick.Particles2::Gravity::acceleration
+ Pixels per second that objects will be accelerated by.
*/
/*!
\qmlproperty real QtQuick.Particles2::Gravity::angle
+
+ Angle of acceleration.
*/
QSGGravityAffector::QSGGravityAffector(QSGItem *parent) :
diff --git a/src/declarative/particles/qsgimageparticle.cpp b/src/declarative/particles/qsgimageparticle.cpp
index 89e9a7db8c..2c7f84f809 100644
--- a/src/declarative/particles/qsgimageparticle.cpp
+++ b/src/declarative/particles/qsgimageparticle.cpp
@@ -53,7 +53,6 @@
#include <qsgengine.h>
QT_BEGIN_NAMESPACE
-
//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
@@ -448,68 +447,157 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size)
This element renders a logical particle as an image. The image can be
- colorized
- - roatated
+ - rotated
- deformed
- a sprite-based animation
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::source
+
+ The source image to be used.
+
+ If the image is a sprite animation, use the sprite property instead.
+*/
+/*!
+ \qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
+
+ The sprite or sprites used to draw this particle.
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::colorTable
+
+ An image whose color will be used as a 1D texture to determine color over life. E.g. when
+ the particle is halfway through its lifetime, it will have the color specified halfway
+ across the image.
+
+ This color is blended with the color property and the color of the source image.
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::sizeTable
- Note that currently sizeTable is ignored for sprite particles.
+ An image whose opacity will be used as a 1D texture to determine size over life.
+
+ This property is expected to be removed shortly, in favor of custom easing curves to determine size over life.
*/
/*!
\qmlproperty url QtQuick.Particles2::ImageParticle::opacityTable
+
+ An image whose opacity will be used as a 1D texture to determine size over life.
+
+ This property is expected to be removed shortly, in favor of custom easing curves to determine opacity over life.
*/
/*!
\qmlproperty color QtQuick.Particles2::ImageParticle::color
+
+ If a color is specified, the provided image will be colorized with it.
+
+ Default is white (no change).
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::colorVariation
+
+ This number represents the color variation applied to individual particles.
+ Setting colorVariation is the same as setting redVariation, greenVariation,
+ and blueVariation to the same number.
+
+ Each channel can vary between particle by up to colorVariation from its usual color.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::redVariation
+ The variation in the red color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::greenVariation
+ The variation in the green color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::blueVariation
+ The variation in the blue color channel between particles.
+
+ Color is measured, per channel, from 0.0 to 1.0.
+
+ Default is 0.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::alpha
+ An alpha to be applied to the image. This value is multiplied by the value in
+ the image, and the value in the color property.
+
+ Particles have additive blending, so lower alpha on single particles leads
+ to stronger effects when multiple particles overlap.
+
+ Alpha is measured from 0.0 to 1.0.
+
+ Default is 1.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::alphaVariation
+ The variation in the alpha channel between particles.
+
+ Alpha is measured from 0.0 to 1.0.
+
+ Default is 0.0
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::rotation
+
+ If set the image will be rotated by this many degrees before it is drawn.
+
+ The particle coordinates are not transformed.
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::rotationVariation
+
+ If set the rotation of individual particles will vary by up to this much
+ between particles.
+
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeed
+
+ If set particles will rotate at this speed in degrees/second.
*/
/*!
\qmlproperty real QtQuick.Particles2::ImageParticle::rotationSpeedVariation
+
+ If set the rotationSpeed of individual particles will vary by up to this much
+ between particles.
+
*/
/*!
\qmlproperty bool QtQuick.Particles2::ImageParticle::autoRotation
+
+ If set to true then a rotation will be applied on top of the particles rotation, so
+ that it faces the direction of travel. So to face away from the direction of travel,
+ set autoRotation to true and rotation to 180.
+
+ Default is false
*/
/*!
\qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::xVector
+
+ Allows you to deform the particle image when drawn. The rectangular image will
+ be deformed so that the horizontal sides are in the shape of this vector instead
+ of (1,0).
*/
/*!
\qmlproperty StochasticDirection QtQuick.Particles2::ImageParticle::yVector
-*/
-/*!
- \qmlproperty list<Sprite> QtQuick.Particles2::ImageParticle::sprites
+
+ Allows you to deform the particle image when drawn. The rectangular image will
+ be deformed so that the vertical sides are in the shape of this vector instead
+ of (0,1).
*/
/*!
\qmlproperty EntryEffect QtQuick.Particles2::ImageParticle::entryEffect
@@ -520,7 +608,7 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size)
Acceptable values are
\list
\o None: Particles just appear and disappear.
- \o Fade: Particles fade in from 0. opacity at the start of their life, and fade out to 0. at the end.
+ \o Fade: Particles fade in from 0 opacity at the start of their life, and fade out to 0 at the end.
\o Scale: Particles scale in from 0 size at the start of their life, and scale back to 0 at the end.
\endlist
@@ -724,7 +812,7 @@ void QSGImageParticle::setAutoRotation(bool arg)
reset();
}
-void QSGImageParticle::setXVector(QSGStochasticDirection* arg)
+void QSGImageParticle::setXVector(QSGDirection* arg)
{
if (m_xVector != arg) {
m_xVector = arg;
@@ -734,7 +822,7 @@ void QSGImageParticle::setXVector(QSGStochasticDirection* arg)
reset();
}
-void QSGImageParticle::setYVector(QSGStochasticDirection* arg)
+void QSGImageParticle::setYVector(QSGDirection* arg)
{
if (m_yVector != arg) {
m_yVector = arg;
@@ -1024,13 +1112,14 @@ QSGNode *QSGImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
m_pleaseReset = false;
}
- if (m_system && m_system->isRunning())
+ if (m_system && m_system->isRunning() && !m_system->isPaused()){
prepareNextFrame();
- if (m_rootNode){
- update();
- //### Should I be using dirty geometry too/instead?
- foreach (QSGGeometryNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyMaterial);
+ if (m_rootNode) {
+ update();
+ //### Should I be using dirty geometry too/instead?
+ foreach (QSGGeometryNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyMaterial);
+ }
}
return m_rootNode;
diff --git a/src/declarative/particles/qsgimageparticle_p.h b/src/declarative/particles/qsgimageparticle_p.h
index 5c684f856c..51b3c37775 100644
--- a/src/declarative/particles/qsgimageparticle_p.h
+++ b/src/declarative/particles/qsgimageparticle_p.h
@@ -42,7 +42,7 @@
#ifndef ULTRAPARTICLE_H
#define ULTRAPARTICLE_H
#include "qsgparticlepainter_p.h"
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
#include <QDeclarativeListProperty>
#include <qsgsimplematerial.h>
#include <QtGui/qcolor.h>
@@ -173,9 +173,9 @@ class QSGImageParticle : public QSGParticlePainter
//###Call i/j? Makes more sense to those with vector calculus experience, and I could even add the cirumflex in QML?
//xVector is the vector from the top-left point to the top-right point, and is multiplied by current size
- Q_PROPERTY(QSGStochasticDirection* xVector READ xVector WRITE setXVector NOTIFY xVectorChanged)
+ Q_PROPERTY(QSGDirection* xVector READ xVector WRITE setXVector NOTIFY xVectorChanged)
//yVector is the same, but top-left to bottom-left. The particle is always a parallelogram.
- Q_PROPERTY(QSGStochasticDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged)
+ Q_PROPERTY(QSGDirection* yVector READ yVector WRITE setYVector NOTIFY yVectorChanged)
Q_PROPERTY(QDeclarativeListProperty<QSGSprite> sprites READ sprites)
Q_PROPERTY(EntryEffect entryEffect READ entryEffect WRITE setEntryEffect NOTIFY entryEffectChanged)
@@ -244,9 +244,9 @@ public:
bool autoRotation() const { return m_autoRotation; }
- QSGStochasticDirection* xVector() const { return m_xVector; }
+ QSGDirection* xVector() const { return m_xVector; }
- QSGStochasticDirection* yVector() const { return m_yVector; }
+ QSGDirection* yVector() const { return m_yVector; }
bool bloat() const { return m_bloat; }
@@ -283,9 +283,9 @@ signals:
void autoRotationChanged(bool arg);
- void xVectorChanged(QSGStochasticDirection* arg);
+ void xVectorChanged(QSGDirection* arg);
- void yVectorChanged(QSGStochasticDirection* arg);
+ void yVectorChanged(QSGDirection* arg);
void bloatChanged(bool arg);
@@ -313,9 +313,9 @@ public slots:
void setAutoRotation(bool arg);
- void setXVector(QSGStochasticDirection* arg);
+ void setXVector(QSGDirection* arg);
- void setYVector(QSGStochasticDirection* arg);
+ void setYVector(QSGDirection* arg);
void setBloat(bool arg);
@@ -365,8 +365,8 @@ private:
qreal m_rotationSpeed;
qreal m_rotationSpeedVariation;
bool m_autoRotation;
- QSGStochasticDirection* m_xVector;
- QSGStochasticDirection* m_yVector;
+ QSGDirection* m_xVector;
+ QSGDirection* m_yVector;
QList<QSGSprite*> m_sprites;
QSGSpriteEngine* m_spriteEngine;
diff --git a/src/declarative/particles/qsgitemparticle.cpp b/src/declarative/particles/qsgitemparticle.cpp
index 65407fabf8..c330880980 100644
--- a/src/declarative/particles/qsgitemparticle.cpp
+++ b/src/declarative/particles/qsgitemparticle.cpp
@@ -56,6 +56,49 @@ QT_BEGIN_NAMESPACE
*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::freeze(Item item)
+
+ Suspends the flow of time for the logical particle which item represents, allowing you to control its movement.
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::unfreeze(Item item)
+
+ Restarts the flow of time for the logical particle which item represents, allowing it to be moved by the particle system again.
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::take(Item item, bool prioritize)
+
+ Asks the ItemParticle to take over control of item. It will be emitted when there is a logical particle available.
+
+ By default items form a queue when waiting for a logical particle, but if prioritize is true then it will go immediately to the
+ head of the queue.
+*/
+/*!
+ \qmlmethod void QtQuick.Particles2::ItemParticle::give(Item item)
+
+ Orders the ItemParticle to give you control of the item. It will cease controlling it and the item will lose its association to the logical particle.
+*/
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ItemParticle::fade
+
+ If true, the item will automatically be faded in and out
+ at the ends of its lifetime. If false, you will have to
+ implement any entry effect yourself.
+
+ Default is true.
+*/
+/*!
+ \qmlproperty Component QtQuick.Particles2::ItemParticle::delegate
+
+ An instance of the delegate will be created for every logical
+ particle, and moved along with it.
+*/
+
QSGItemParticle::QSGItemParticle(QSGItem *parent) :
QSGParticlePainter(parent), m_fade(true), m_delegate(0)
{
diff --git a/src/declarative/particles/qsgmaskextruder.cpp b/src/declarative/particles/qsgmaskextruder.cpp
index 4f8b89a639..6facfac353 100644
--- a/src/declarative/particles/qsgmaskextruder.cpp
+++ b/src/declarative/particles/qsgmaskextruder.cpp
@@ -52,6 +52,9 @@ QT_BEGIN_NAMESPACE
*/
/*!
\qmlproperty url QtQuick.Particles2::MaskShape::source
+
+ The image to use as the mask. Areas with non-zero opacity
+ will be considered inside the shape.
*/
diff --git a/src/declarative/particles/qsgmodelparticle.cpp b/src/declarative/particles/qsgmodelparticle.cpp
deleted file mode 100644
index d90b09fa6d..0000000000
--- a/src/declarative/particles/qsgmodelparticle.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 "qsgmodelparticle_p.h"
-#include <QtDeclarative/private/qsgvisualitemmodel_p.h>
-#include <qsgnode.h>
-#include <QTimer>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass ModelParticle QSGModelParticle
- \inqmlmodule QtQuick.Particles 2
- \inherits ParticlePainter
- \brief The ModelParticle element allows you to specify a model and delegate pair to paint particles.
-
-*/
-
-
-QSGModelParticle::QSGModelParticle(QSGItem *parent) :
- QSGParticlePainter(parent), m_ownModel(false), m_comp(0), m_model(0), m_fade(true), m_modelCount(0)
-{
- setFlag(QSGItem::ItemHasContents);
- QTimer* manageDelegates = new QTimer(this);//TODO: don't leak
- connect(manageDelegates, SIGNAL(timeout()),
- this, SLOT(processPending()));
- manageDelegates->setInterval(16);
- manageDelegates->setSingleShot(false);
- manageDelegates->start();
-}
-
-QSGModelParticle::~QSGModelParticle()
-{
- if (m_ownModel)
- delete m_model;
-}
-
-QVariant QSGModelParticle::model() const
-{
- return m_dataSource;
-}
-
-void QSGModelParticle::setModel(const QVariant &arg)
-{
- if (arg == m_dataSource)
- return;
- m_dataSource = arg;
- if (qobject_cast<QSGVisualDataModel*>(arg.value<QObject*>())) {
- if (m_ownModel && m_model)
- delete m_model;
- m_model = qobject_cast<QSGVisualDataModel*>(arg.value<QObject*>());
- m_ownModel = false;
- }else{
- if (!m_model || !m_ownModel)
- m_model = new QSGVisualDataModel(qmlContext(this));
- m_model->setModel(m_dataSource);
- m_ownModel = true;
- }
- if (m_comp)
- m_model->setDelegate(m_comp);
- emit modelChanged();
- emit modelCountChanged();
- connect(m_model, SIGNAL(countChanged()),
- this, SIGNAL(modelCountChanged()));
- connect(m_model, SIGNAL(countChanged()),
- this, SLOT(updateCount()));
- updateCount();
-}
-
-void QSGModelParticle::updateCount()
-{
- int newCount = 0;
- if (m_model)
- newCount = m_model->count();
- if (newCount < 0)
- return;//WTF?
- if (m_modelCount == 0 || newCount == 0){
- m_available.clear();
- for (int i=0; i<newCount; i++)
- m_available << i;
- }else if (newCount < m_modelCount){
- for (int i=newCount; i<m_modelCount; i++) //existing ones must leave normally, but aren't readded
- m_available.removeAll(i);
- }else if (newCount > m_modelCount){
- for (int i=m_modelCount; i<newCount; i++)
- m_available << i;
- }
- m_modelCount = newCount;
-}
-
-QDeclarativeComponent *QSGModelParticle::delegate() const
-{
- if (m_model)
- return m_model->delegate();
- return 0;
-}
-
-void QSGModelParticle::setDelegate(QDeclarativeComponent *comp)
-{
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(m_model))
- if (comp == dataModel->delegate())
- return;
- m_comp = comp;
- if (m_model)
- m_model->setDelegate(comp);
- emit delegateChanged();
-}
-
-int QSGModelParticle::modelCount() const
-{
- if (m_model)
- const_cast<QSGModelParticle*>(this)->updateCount();//TODO: Investigate why this doesn't get called properly
- return m_modelCount;
-}
-
-
-void QSGModelParticle::freeze(QSGItem* item)
-{
- m_stasis << item;
-}
-
-
-void QSGModelParticle::unfreeze(QSGItem* item)
-{
- m_stasis.remove(item);
-}
-
-void QSGModelParticle::initialize(int gIdx, int pIdx)
-{
- if (!m_model || !m_model->count())
- return;
- if (m_available.isEmpty())
- return;
- m_requests << m_system->m_groupData[gIdx]->data[pIdx];
-}
-
-void QSGModelParticle::processPending()
-{//can't create/delete arbitrary items in the render thread
- foreach (QSGItem* item, m_deletables){
- item->setVisible(false);
- if (m_fade)
- item->setOpacity(0.);
- m_model->release(item);
- m_activeCount--;
- }
- m_deletables.clear();
-
- foreach (QSGParticleData* datum, m_requests){
- if (datum->delegate){
- if (m_stasis.contains(datum->delegate))
- qWarning() << "Current model particles prefers overwrite:false";
- //remove old item from the particle that is dying to make room for this one
- m_deletables << datum->delegate;
- m_available << datum->modelIndex;
- datum->modelIndex = -1;
- datum->delegate = 0;
- }
-
- if (!m_available.isEmpty()){
- datum->delegate = m_model->item(m_available.first());
- datum->modelIndex = m_available.first();
- m_available.pop_front();
- QSGModelParticleAttached* mpa = qobject_cast<QSGModelParticleAttached*>(qmlAttachedPropertiesObject<QSGModelParticle>(datum->delegate));
- if (mpa){
- mpa->m_mp = this;
- mpa->attach();
- }
- datum->delegate->setParentItem(this);
- if (m_fade)
- datum->delegate->setOpacity(0.0);
- datum->delegate->setVisible(false);//Will be set to true when we prepare the next frame
- m_activeCount++;
- }
- }
- m_requests.clear();
-}
-
-void QSGModelParticle::commit(int /* gIdx */, int /* pIdx */)
-{
- //No-op unless we start copying the data.
-}
-
-void QSGModelParticle::reset()
-{
- QSGParticlePainter::reset();
- //TODO: Cleanup items?
- //m_available.clear();//Should this be reset too?
- //m_pendingItems.clear();//TODO: Should this be done? If so, Emit signal?
-}
-
-
-QSGNode* QSGModelParticle::updatePaintNode(QSGNode* n, UpdatePaintNodeData* d)
-{
- //Dummy update just to get painting tick
- if (m_pleaseReset){
- m_pleaseReset = false;
- reset();
- }
- prepareNextFrame();
-
- update();//Get called again
- if (n)
- n->markDirty(QSGNode::DirtyMaterial);
- return QSGItem::updatePaintNode(n,d);
-}
-
-void QSGModelParticle::prepareNextFrame()
-{
- if (!m_system)
- return;
- qint64 timeStamp = m_system->systemSync(this);
- qreal curT = timeStamp/1000.0;
- qreal dt = curT - m_lastT;
- m_lastT = curT;
- if (!m_activeCount)
- return;
-
- //TODO: Size, better fade?
- foreach (const QString &str, m_particles){
- int gIdx = m_system->m_groupIds[str];
- int count = m_system->m_groupData[gIdx]->size();
-
- for (int i=0; i<count; i++){
- QSGParticleData* data = m_system->m_groupData[gIdx]->data[i];
- if (!data || !data->delegate)
- continue;
- qreal t = ((timeStamp/1000.0) - data->t) / data->lifeSpan;
- if (m_stasis.contains(data->delegate)) {
- data->t += dt;//Stasis effect
- continue;
- }
- if (t >= 1.0){//Usually happens from load
- m_available << data->modelIndex;
- m_deletables << data->delegate;
- data->modelIndex = -1;
- data->delegate = 0;
- continue;
- }else{//Fade
- data->delegate->setVisible(true);
- if (m_fade){
- qreal o = 1.;
- if (t<0.2)
- o = t*5;
- if (t>0.8)
- o = (1-t)*5;
- data->delegate->setOpacity(o);
- }
- }
- data->delegate->setX(data->curX() - data->delegate->width()/2 - m_systemOffset.x());
- data->delegate->setY(data->curY() - data->delegate->height()/2 - m_systemOffset.y());
- }
- }
-}
-
-QSGModelParticleAttached *QSGModelParticle::qmlAttachedProperties(QObject *object)
-{
- return new QSGModelParticleAttached(object);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgmodelparticle_p.h b/src/declarative/particles/qsgmodelparticle_p.h
deleted file mode 100644
index c6dd40d51e..0000000000
--- a/src/declarative/particles/qsgmodelparticle_p.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Declarative 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 DATAPARTICLE_H
-#define DATAPARTICLE_H
-#include "qsgparticlepainter_p.h"
-#include <QPointer>
-#include <QSet>
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-class QSGVisualDataModel;
-class QSGModelParticleAttached;
-
-class QSGModelParticle : public QSGParticlePainter
-{
- Q_OBJECT
-
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int modelCount READ modelCount NOTIFY modelCountChanged)
- Q_PROPERTY(bool fade READ fade WRITE setFade NOTIFY fadeChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-public:
- explicit QSGModelParticle(QSGItem *parent = 0);
- virtual ~QSGModelParticle();
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int modelCount() const;
-
- bool fade() const { return m_fade; }
-
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
- static QSGModelParticleAttached *qmlAttachedProperties(QObject *object);
-signals:
- void modelChanged();
- void delegateChanged();
- void modelCountChanged();
- void fadeChanged();
-
-public slots:
- void freeze(QSGItem* item);
- void unfreeze(QSGItem* item);
-
- void setFade(bool arg){if (arg == m_fade) return; m_fade = arg; emit fadeChanged();}
-protected:
- virtual void reset();
- virtual void commit(int gIdx, int pIdx);
- virtual void initialize(int gIdx, int pIdx);
- void prepareNextFrame();
-private slots:
- void updateCount();
- void processPending();
-private:
- bool m_ownModel;
- QDeclarativeComponent* m_comp;
- QSGVisualDataModel *m_model;
- QVariant m_dataSource;
- QList<QSGItem*> m_deletables;
- QList< QSGParticleData* > m_requests;
- bool m_fade;
-
- QList<QSGItem*> m_pendingItems;
- QList<int> m_available;
- QSet<QSGItem*> m_stasis;
- qreal m_lastT;
- int m_activeCount;
- int m_modelCount;
-};
-
-class QSGModelParticleAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QSGModelParticle* particle READ particle CONSTANT)
-public:
- QSGModelParticleAttached(QObject* parent)
- : QObject(parent), m_mp(0)
- {;}
- QSGModelParticle* particle() {return m_mp;}
- void detach(){emit detached();}
- void attach(){emit attached();}
-private:
- QSGModelParticle* m_mp;
- friend class QSGModelParticle;
-Q_SIGNALS:
- void detached();
- void attached();
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPEINFO(QSGModelParticle, QML_HAS_ATTACHED_PROPERTIES)
-
-QT_END_HEADER
-#endif // DATAPARTICLE_H
diff --git a/src/declarative/particles/qsgparticleaffector.cpp b/src/declarative/particles/qsgparticleaffector.cpp
index 331310625f..3554121a2b 100644
--- a/src/declarative/particles/qsgparticleaffector.cpp
+++ b/src/declarative/particles/qsgparticleaffector.cpp
@@ -73,16 +73,16 @@ QT_BEGIN_NAMESPACE
By default, no groups are specified.
*/
/*!
- \qmlproperty bool QtQuick.Particles2::Affector::active
- If active is set to false, this affector will not affect any particles.
+ \qmlproperty bool QtQuick.Particles2::Affector::enabled
+ If enabled is set to false, this affector will not affect any particles.
Usually this is used to conditionally turn an affector on or off.
Default value is true.
*/
/*!
- \qmlproperty bool QtQuick.Particles2::Affector::onceOff
- If onceOff is set to true, this affector will only affect each particle
+ \qmlproperty bool QtQuick.Particles2::Affector::once
+ If once is set to true, this affector will only affect each particle
once in their lifetimes.
Default value is false.
@@ -93,65 +93,67 @@ QT_BEGIN_NAMESPACE
non-rectangular area.
*/
/*!
- \qmlproperty bool QtQuick.Particles2::Affector::signal
- If this is set to true, then an affected(x,y) signal will be emitted each
- time this affector would affect a particle.
+ \qmlsignal QtQuick.Particles2::Affector::onAffected(x, y)
- For Affector only, this will happen irrespective of whether any changes
- are made to the particle, for other Affectors the signal will only fire
- if the particle is actually affected.
+ This signal is emitted each time the affector actually affects a particle.
- Default value is false.
-*/
+ x,y are the coordinates of the affected particle, relative to the ParticleSystem.
+*/
//TODO: Document particle 'type'
/*!
\qmlsignal QtQuick.Particles2::Affector::affectParticle(particle, dt)
- This handler is called when a particle is selected to be affected.
+ This handler is called when particles are selected to be affected.
dt is the time since the last time it was affected. Use dt to normalize
trajectory manipulations to real time.
+
+ Note that JS is slower to execute, so it is not recommended to use this in
+ high-volume particle systems.
+*/
+/*!
+ \qmlsignal QtQuick.Particles2::Affector::affected(x, y)
+
+ This handler is called when a particle is selected to be affected. It will
+ only be called if signal is set to true.
+
+ x,y is the particles current position.
*/
QSGParticleAffector::QSGParticleAffector(QSGItem *parent) :
- QSGItem(parent), m_needsReset(false), m_system(0), m_active(true)
- , m_updateIntSet(false), m_shape(new QSGParticleExtruder(this)), m_signal(false)
+ QSGItem(parent), m_needsReset(false), m_system(0), m_enabled(true)
+ , m_updateIntSet(false), m_shape(new QSGParticleExtruder(this))
{
- connect(this, SIGNAL(systemChanged(QSGParticleSystem*)),
- this, SLOT(updateOffsets()));
- connect(this, SIGNAL(xChanged()),
- this, SLOT(updateOffsets()));
- connect(this, SIGNAL(yChanged()),
- this, SLOT(updateOffsets()));//TODO: in componentComplete and all relevant signals
}
-bool QSGParticleAffector::isAffectConnected()
+bool QSGParticleAffector::isAffectedConnected()
{
- static int idx = QObjectPrivate::get(this)->signalIndex("affectParticle(QDeclarativeV8Handle, qreal)");
+ static int idx = QObjectPrivate::get(this)->signalIndex("affected(qreal,qreal)");
return QObjectPrivate::get(this)->isSignalConnected(idx);
}
+
void QSGParticleAffector::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
setSystem(qobject_cast<QSGParticleSystem*>(parentItem()));
- if (!m_system)
- qWarning() << "Affector created without a particle system specified";//TODO: useful QML warnings, like line number?
QSGItem::componentComplete();
}
void QSGParticleAffector::affectSystem(qreal dt)
{
- if (!m_active)
+ if (!m_enabled)
return;
//If not reimplemented, calls affect particle per particle
//But only on particles in targeted system/area
+ bool affectedConnected = isAffectedConnected();
if (m_updateIntSet){
m_groups.clear();
foreach (const QString &p, m_particles)
m_groups << m_system->m_groupIds[p];//###Can this occur before group ids are properly assigned?
m_updateIntSet = false;
}
+ updateOffsets();//### Needed if an ancestor is transformed.
foreach (QSGParticleGroupData* gd, m_system->m_groupData){
foreach (QSGParticleData* d, gd->data){
if (!d)
@@ -162,16 +164,16 @@ void QSGParticleAffector::affectSystem(qreal dt)
continue;
//Need to have previous location for affected anyways
QPointF curPos;
- if (m_signal || (width() && height()))
+ if (affectedConnected || (width() && height()))
curPos = QPointF(d->curX(), d->curY());
if (width() == 0 || height() == 0
|| m_shape->contains(QRectF(m_offset.x(), m_offset.y(), width(), height()),curPos)){
- if (m_collisionParticles.isEmpty() || isColliding(d)){
+ if (m_whenCollidingWith.isEmpty() || isColliding(d)){
if (affectParticle(d, dt)){
m_system->m_needsReset << d;
if (m_onceOff)
m_onceOffed << qMakePair(d->group, d->index);
- if (m_signal)
+ if (affectedConnected)
emit affected(curPos.x(), curPos.y());
}
}
@@ -183,12 +185,7 @@ void QSGParticleAffector::affectSystem(qreal dt)
bool QSGParticleAffector::affectParticle(QSGParticleData *d, qreal dt)
{
- if (isAffectConnected()){
- d->update = 0.0;
- emit affectParticle(d->v8Value(), dt);
- return d->update == 1.0;
- }
- return m_signal;//If signalling, then we always 'null affect' it.
+ return true;
}
void QSGParticleAffector::reset(QSGParticleData* pd)
@@ -209,7 +206,7 @@ bool QSGParticleAffector::isColliding(QSGParticleData *d)
qreal myCurX = d->curX();
qreal myCurY = d->curY();
qreal myCurSize = d->curSize()/2;
- foreach (const QString &group, m_collisionParticles){
+ foreach (const QString &group, m_whenCollidingWith){
foreach (QSGParticleData* other, m_system->m_groupData[m_system->m_groupIds[group]]->data){
if (!other->stillAlive())
continue;
diff --git a/src/declarative/particles/qsgparticleaffector_p.h b/src/declarative/particles/qsgparticleaffector_p.h
index dd279c07b9..c808ef4e76 100644
--- a/src/declarative/particles/qsgparticleaffector_p.h
+++ b/src/declarative/particles/qsgparticleaffector_p.h
@@ -57,11 +57,10 @@ class QSGParticleAffector : public QSGItem
Q_OBJECT
Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
Q_PROPERTY(QStringList particles READ particles WRITE setParticles NOTIFY particlesChanged)
- Q_PROPERTY(QStringList collisionParticles READ collisionParticles WRITE setCollisionParticles NOTIFY collisionParticlesChanged)
- Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(bool onceOff READ onceOff WRITE setOnceOff NOTIFY onceOffChanged)
+ Q_PROPERTY(QStringList whenCollidingWith READ whenCollidingWith WRITE setWhenCollidingWith NOTIFY whenCollidingWithChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool once READ onceOff WRITE setOnceOff NOTIFY onceChanged)
Q_PROPERTY(QSGParticleExtruder* shape READ shape WRITE setShape NOTIFY shapeChanged)
- Q_PROPERTY(bool signal READ signal WRITE setSignal NOTIFY signalChanged)//TODO: Determine by whether it's connected
public:
explicit QSGParticleAffector(QSGItem *parent = 0);
@@ -77,9 +76,9 @@ public:
return m_particles;
}
- bool active() const
+ bool enabled() const
{
- return m_active;
+ return m_enabled;
}
bool onceOff() const
@@ -92,33 +91,26 @@ public:
return m_shape;
}
- bool signal() const
+ QStringList whenCollidingWith() const
{
- return m_signal;
- }
-
- QStringList collisionParticles() const
- {
- return m_collisionParticles;
+ return m_whenCollidingWith;
}
signals:
- void affectParticle(QDeclarativeV8Handle particle, qreal dt);
void systemChanged(QSGParticleSystem* arg);
void particlesChanged(QStringList arg);
- void activeChanged(bool arg);
+ void enabledChanged(bool arg);
- void onceOffChanged(bool arg);
+ void onceChanged(bool arg);
void shapeChanged(QSGParticleExtruder* arg);
void affected(qreal x, qreal y);
- void signalChanged(bool arg);
- void collisionParticlesChanged(QStringList arg);
+ void whenCollidingWithChanged(QStringList arg);
public slots:
void setSystem(QSGParticleSystem* arg)
@@ -139,11 +131,11 @@ void setParticles(QStringList arg)
}
}
-void setActive(bool arg)
+void setEnabled(bool arg)
{
- if (m_active != arg) {
- m_active = arg;
- emit activeChanged(arg);
+ if (m_enabled != arg) {
+ m_enabled = arg;
+ emit enabledChanged(arg);
}
}
@@ -152,7 +144,7 @@ void setOnceOff(bool arg)
if (m_onceOff != arg) {
m_onceOff = arg;
m_needsReset = true;
- emit onceOffChanged(arg);
+ emit onceChanged(arg);
}
}
@@ -164,19 +156,11 @@ void setShape(QSGParticleExtruder* arg)
}
}
-void setSignal(bool arg)
-{
- if (m_signal != arg) {
- m_signal = arg;
- emit signalChanged(arg);
- }
-}
-
-void setCollisionParticles(QStringList arg)
+void setWhenCollidingWith(QStringList arg)
{
- if (m_collisionParticles != arg) {
- m_collisionParticles = arg;
- emit collisionParticlesChanged(arg);
+ if (m_whenCollidingWith != arg) {
+ m_whenCollidingWith = arg;
+ emit whenCollidingWithChanged(arg);
}
}
@@ -187,10 +171,10 @@ protected:
QSGParticleSystem* m_system;
QStringList m_particles;
bool activeGroup(int g) {return m_groups.isEmpty() || m_groups.contains(g);}
- bool m_active;
+ bool m_enabled;
virtual void componentComplete();
QPointF m_offset;
- bool isAffectConnected();
+ bool isAffectedConnected();
private:
QSet<int> m_groups;
QSet<QPair<int, int> > m_onceOffed;
@@ -200,9 +184,7 @@ private:
QSGParticleExtruder* m_shape;
- bool m_signal;
-
- QStringList m_collisionParticles;
+ QStringList m_whenCollidingWith;
bool isColliding(QSGParticleData* d);
private slots:
diff --git a/src/declarative/particles/qsgparticleemitter.cpp b/src/declarative/particles/qsgparticleemitter.cpp
index bf4f5701e5..d44ad689ee 100644
--- a/src/declarative/particles/qsgparticleemitter.cpp
+++ b/src/declarative/particles/qsgparticleemitter.cpp
@@ -100,6 +100,12 @@ QT_BEGIN_NAMESPACE
The time in milliseconds each emitted particle should last for.
+ If you do not want particles to automatically die after a time, for example if
+ you wish to dispose of them manually, set lifeSpan to Emitter.InfiniteLife.
+
+ lifeSpans greater than or equal to 600000 (10 minutes) will be treated as infinite.
+ Particles with lifeSpans less than or equal to 0 will start out dead.
+
Default value is 1000 (one second).
*/
/*!
@@ -111,21 +117,17 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlproperty int QtQuick.Particles2::Emitter::emitCap
+ \qmlproperty int QtQuick.Particles2::Emitter::maximumEmitted
The maximum number of particles at a time that this emitter will have alive.
This can be set as a performance optimization (when using burst and pulse) or
- to stagger emissions. The default value is emitRate * lifeSpan in seconds, which
- is the number of particles that would be alive at any one time given the default settings.
-*/
-/*!
- \qmlproperty bool QtQuick.Particles2::Emitter::noCap
+ to stagger emissions.
- If set to true, the emitCap will be ignored and this emitter will never skip emitting
- a particle based on how many it has alive.
+ If this is set to a number below zero, then there is no maximum limit on the number
+ of particles this emitter can have alive.
- Default value is false.
+ The default value is -1.
*/
/*!
\qmlproperty int QtQuick.Particles2::Emitter::startTime
@@ -181,19 +183,38 @@ QT_BEGIN_NAMESPACE
*/
//TODO: Document particle 'type'
/*!
- \qmlsignal QtQuick.Particles2::Emitter::emitParticle(particle)
+ \qmlsignal QtQuick.Particles2::Emitter::onEmitParticle(Particle particle)
This handler is called when a particle is emitted. You can modify particle
attributes from within the handler.
+
+ Note that JS is slower to execute, so it is not recommended to use this in
+ high-volume particle systems.
+*/
+
+/*! \qmlmethod QtQuick.Particles2::Emitter::burst(int count)
+
+ Emits count particles from this emitter immediately.
+*/
+
+/*! \qmlmethod QtQuick.Particles2::Emitter::burst(int x, int y, int count)
+
+ Emits count particles from this emitter immediately. The particles are emitted
+ as if the Emitter was positioned at x,y but all other properties are the same.
*/
+/*! \qmlmethod QtQuick.Particles2::Emitter::pulse(real duration)
+
+ If the emitter is not enabled, enables it for duration seconds and then switches
+ it back off.
+*/
QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
QSGItem(parent)
, m_particlesPerSecond(10)
, m_particleDuration(1000)
, m_particleDurationVariation(0)
- , m_emitting(true)
+ , m_enabled(true)
, m_system(0)
, m_extruder(0)
, m_defaultExtruder(0)
@@ -205,16 +226,15 @@ QSGParticleEmitter::QSGParticleEmitter(QSGItem *parent) :
, m_maxParticleCount(-1)
, m_burstLeft(0)
, m_speed_from_movement(0)
- , m_particle_count(0)
, m_reset_last(true)
, m_last_timestamp(-1)
, m_last_emission(0)
, m_startTime(0)
- , m_overwrite(false)
+ , m_overwrite(true)
{
//TODO: Reset speed/acc back to null vector? Or allow null pointer?
- connect(this, SIGNAL(maxParticleCountChanged(int)),
+ connect(this, SIGNAL(maximumEmittedChanged(int)),
this, SIGNAL(particleCountChanged()));
connect(this, SIGNAL(particlesPerSecondChanged(qreal)),
this, SIGNAL(particleCountChanged()));
@@ -238,16 +258,14 @@ void QSGParticleEmitter::componentComplete()
{
if (!m_system && qobject_cast<QSGParticleSystem*>(parentItem()))
setSystem(qobject_cast<QSGParticleSystem*>(parentItem()));
- if (!m_system)
- qWarning() << "Emitter created without a particle system specified";//TODO: useful QML warnings, like line number?
QSGItem::componentComplete();
}
-void QSGParticleEmitter::setEmitting(bool arg)
+void QSGParticleEmitter::setEnabled(bool arg)
{
- if (m_emitting != arg) {
- m_emitting = arg;
- emit emittingChanged(arg);
+ if (m_enabled != arg) {
+ m_enabled = arg;
+ emit enabledChanged(arg);
}
}
@@ -265,7 +283,7 @@ void QSGParticleEmitter::pulse(qreal seconds)
{
if (!particleCount())
qWarning() << "pulse called on an emitter with a particle count of zero";
- if (!m_emitting)
+ if (!m_enabled)
m_burstLeft = seconds*1000.0;//TODO: Change name to match
}
@@ -297,8 +315,9 @@ void QSGParticleEmitter::setMaxParticleCount(int arg)
disconnect(this, SIGNAL(particleDurationChanged(int)),
this, SIGNAL(particleCountChanged()));
}
+ m_overwrite = arg < 0;
m_maxParticleCount = arg;
- emit maxParticleCountChanged(arg);
+ emit maximumEmittedChanged(arg);
}
}
@@ -317,11 +336,16 @@ void QSGParticleEmitter::setSpeedFromMovement(qreal t)
emit speedFromMovementChanged();
}
+void QSGParticleEmitter::reset()
+{
+ m_reset_last = true;
+}
+
void QSGParticleEmitter::emitWindow(int timeStamp)
{
if (m_system == 0)
return;
- if ((!m_emitting || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
+ if ((!m_enabled || !m_particlesPerSecond)&& !m_burstLeft && m_burstQueue.isEmpty()){
m_reset_last = true;
return;
}
@@ -329,24 +353,23 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
if (m_reset_last) {
m_last_emitter = m_last_last_emitter = QPointF(x(), y());
if (m_last_timestamp == -1)
- m_last_timestamp = timeStamp/1000. - m_startTime;
+ m_last_timestamp = (timeStamp - m_startTime)/1000.;
else
m_last_timestamp = timeStamp/1000.;
m_last_emission = m_last_timestamp;
m_reset_last = false;
+ m_emitCap = particleCount();
}
if (m_burstLeft){
m_burstLeft -= timeStamp - m_last_timestamp * 1000.;
if (m_burstLeft < 0){
- if (!m_emitting)
+ if (!m_enabled)
timeStamp += m_burstLeft;
m_burstLeft = 0;
}
}
-
qreal time = timeStamp / 1000.;
-
qreal particleRatio = 1. / m_particlesPerSecond;
qreal pt = m_last_emission;
@@ -369,9 +392,9 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
qreal sizeAtEnd = m_particleEndSize >= 0 ? m_particleEndSize : m_particleSize;
qreal emitter_x_offset = m_last_emitter.x() - x();
qreal emitter_y_offset = m_last_emitter.y() - y();
- if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_emitting)//'outside time' emissions only
+ if (!m_burstQueue.isEmpty() && !m_burstLeft && !m_enabled)//'outside time' emissions only
pt = time;
- while (pt < time || !m_burstQueue.isEmpty()) {
+ while ((pt < time && m_emitCap) || !m_burstQueue.isEmpty()) {
//int pos = m_last_particle % m_particle_count;
QSGParticleData* datum = m_system->newDatum(m_system->m_groupIds[m_particle], !m_overwrite);
if (datum){//actually emit(otherwise we've been asked to skip this one)
@@ -389,11 +412,16 @@ void QSGParticleEmitter::emitWindow(int timeStamp)
// Particle timestamp
datum->t = pt;
- datum->lifeSpan = //TODO:Promote to base class?
+ datum->lifeSpan =
(m_particleDuration
+ ((rand() % ((m_particleDurationVariation*2) + 1)) - m_particleDurationVariation))
/ 1000.0;
+ if (datum->lifeSpan >= m_system->maxLife){
+ datum->lifeSpan = m_system->maxLife;
+ m_emitCap--;//emitCap keeps us from reemitting 'infinite' particles after their life. Unless you reset the emitter.
+ }
+
// Particle position
QRectF boundsRect;
if (!m_burstQueue.isEmpty()){
diff --git a/src/declarative/particles/qsgparticleemitter_p.h b/src/declarative/particles/qsgparticleemitter_p.h
index 2c75fbfe22..8ed7ee7053 100644
--- a/src/declarative/particles/qsgparticleemitter_p.h
+++ b/src/declarative/particles/qsgparticleemitter_p.h
@@ -46,7 +46,7 @@
#include <QDebug>
#include "qsgparticlesystem_p.h"
#include "qsgparticleextruder_p.h"
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
#include <QList>
#include <QPair>
@@ -63,31 +63,35 @@ class QSGParticleEmitter : public QSGItem
Q_PROPERTY(QSGParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
Q_PROPERTY(QString particle READ particle WRITE setParticle NOTIFY particleChanged)
Q_PROPERTY(QSGParticleExtruder* shape READ extruder WRITE setExtruder NOTIFY extruderChanged)
- Q_PROPERTY(bool emitting READ emitting WRITE setEmitting NOTIFY emittingChanged)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
- Q_PROPERTY(bool noCap READ overwrite WRITE setOverWrite NOTIFY overwriteChanged)
Q_PROPERTY(qreal emitRate READ particlesPerSecond WRITE setParticlesPerSecond NOTIFY particlesPerSecondChanged)
Q_PROPERTY(int lifeSpan READ particleDuration WRITE setParticleDuration NOTIFY particleDurationChanged)
Q_PROPERTY(int lifeSpanVariation READ particleDurationVariation WRITE setParticleDurationVariation NOTIFY particleDurationVariationChanged)
- Q_PROPERTY(int emitCap READ maxParticleCount WRITE setMaxParticleCount NOTIFY maxParticleCountChanged)
+ Q_PROPERTY(int maximumEmitted READ maxParticleCount WRITE setMaxParticleCount NOTIFY maximumEmittedChanged)
Q_PROPERTY(qreal size READ particleSize WRITE setParticleSize NOTIFY particleSizeChanged)
Q_PROPERTY(qreal endSize READ particleEndSize WRITE setParticleEndSize NOTIFY particleEndSizeChanged)
Q_PROPERTY(qreal sizeVariation READ particleSizeVariation WRITE setParticleSizeVariation NOTIFY particleSizeVariationChanged)
- Q_PROPERTY(QSGStochasticDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
- Q_PROPERTY(QSGStochasticDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
+ Q_PROPERTY(QSGDirection *speed READ speed WRITE setSpeed NOTIFY speedChanged)
+ Q_PROPERTY(QSGDirection *acceleration READ acceleration WRITE setAcceleration NOTIFY accelerationChanged)
Q_PROPERTY(qreal speedFromMovement READ speedFromMovement WRITE setSpeedFromMovement NOTIFY speedFromMovementChanged)
+ Q_ENUMS(Lifetime)
public:
explicit QSGParticleEmitter(QSGItem *parent = 0);
virtual ~QSGParticleEmitter();
virtual void emitWindow(int timeStamp);
- bool emitting() const
+ enum Lifetime {
+ InfiniteLife = QSGParticleSystem::maxLife
+ };
+
+ bool enabled() const
{
- return m_emitting;
+ return m_enabled;
}
qreal particlesPerSecond() const
@@ -122,7 +126,7 @@ signals:
void emitParticle(QDeclarativeV8Handle particle);
void particlesPerSecondChanged(qreal);
void particleDurationChanged(int);
- void emittingChanged(bool);
+ void enabledChanged(bool);
void systemChanged(QSGParticleSystem* arg);
@@ -138,25 +142,23 @@ signals:
void particleSizeVariationChanged(qreal arg);
- void speedChanged(QSGStochasticDirection * arg);
+ void speedChanged(QSGDirection * arg);
- void accelerationChanged(QSGStochasticDirection * arg);
+ void accelerationChanged(QSGDirection * arg);
- void maxParticleCountChanged(int arg);
+ void maximumEmittedChanged(int arg);
void particleCountChanged();
void speedFromMovementChanged();
void startTimeChanged(int arg);
- void overwriteChanged(bool arg);
-
public slots:
void pulse(qreal seconds);
void burst(int num);
void burst(int num, qreal x, qreal y);
- void setEmitting(bool arg);
+ void setEnabled(bool arg);
void setParticlesPerSecond(qreal arg)
{
@@ -174,100 +176,92 @@ public slots:
}
}
- void setSystem(QSGParticleSystem* arg)
+ void setSystem(QSGParticleSystem* arg)
{
if (m_system != arg) {
m_system = arg;
m_system->registerParticleEmitter(this);
emit systemChanged(arg);
}
- }
-
- void setParticle(QString arg)
- {
- if (m_particle != arg) {
- m_particle = arg;
- emit particleChanged(arg);
- }
- }
+ }
- void setParticleDurationVariation(int arg)
- {
- if (m_particleDurationVariation != arg) {
- m_particleDurationVariation = arg;
- emit particleDurationVariationChanged(arg);
- }
- }
- void setExtruder(QSGParticleExtruder* arg)
- {
- if (m_extruder != arg) {
- m_extruder = arg;
- emit extruderChanged(arg);
- }
- }
+ void setParticle(QString arg)
+ {
+ if (m_particle != arg) {
+ m_particle = arg;
+ emit particleChanged(arg);
+ }
+ }
- void setParticleSize(qreal arg)
- {
- if (m_particleSize != arg) {
- m_particleSize = arg;
- emit particleSizeChanged(arg);
- }
- }
+ void setParticleDurationVariation(int arg)
+ {
+ if (m_particleDurationVariation != arg) {
+ m_particleDurationVariation = arg;
+ emit particleDurationVariationChanged(arg);
+ }
+ }
+ void setExtruder(QSGParticleExtruder* arg)
+ {
+ if (m_extruder != arg) {
+ m_extruder = arg;
+ emit extruderChanged(arg);
+ }
+ }
- void setParticleEndSize(qreal arg)
- {
- if (m_particleEndSize != arg) {
- m_particleEndSize = arg;
- emit particleEndSizeChanged(arg);
- }
- }
+ void setParticleSize(qreal arg)
+ {
+ if (m_particleSize != arg) {
+ m_particleSize = arg;
+ emit particleSizeChanged(arg);
+ }
+ }
- void setParticleSizeVariation(qreal arg)
- {
- if (m_particleSizeVariation != arg) {
- m_particleSizeVariation = arg;
- emit particleSizeVariationChanged(arg);
- }
- }
+ void setParticleEndSize(qreal arg)
+ {
+ if (m_particleEndSize != arg) {
+ m_particleEndSize = arg;
+ emit particleEndSizeChanged(arg);
+ }
+ }
- void setSpeed(QSGStochasticDirection * arg)
- {
- if (m_speed != arg) {
- m_speed = arg;
- emit speedChanged(arg);
- }
- }
+ void setParticleSizeVariation(qreal arg)
+ {
+ if (m_particleSizeVariation != arg) {
+ m_particleSizeVariation = arg;
+ emit particleSizeVariationChanged(arg);
+ }
+ }
- void setAcceleration(QSGStochasticDirection * arg)
- {
- if (m_acceleration != arg) {
- m_acceleration = arg;
- emit accelerationChanged(arg);
- }
- }
+ void setSpeed(QSGDirection * arg)
+ {
+ if (m_speed != arg) {
+ m_speed = arg;
+ emit speedChanged(arg);
+ }
+ }
- void setMaxParticleCount(int arg);
+ void setAcceleration(QSGDirection * arg)
+ {
+ if (m_acceleration != arg) {
+ m_acceleration = arg;
+ emit accelerationChanged(arg);
+ }
+ }
- void setStartTime(int arg)
- {
- if (m_startTime != arg) {
- m_startTime = arg;
- emit startTimeChanged(arg);
- }
- }
+ void setMaxParticleCount(int arg);
- void setOverWrite(bool arg)
-{
- if (m_overwrite != arg) {
- m_overwrite = arg;
-emit overwriteChanged(arg);
-}
-}
+ void setStartTime(int arg)
+ {
+ if (m_startTime != arg) {
+ m_startTime = arg;
+ emit startTimeChanged(arg);
+ }
+ }
+ virtual void reset();
public:
int particleCount() const;
- virtual void reset(){;}
QSGParticleExtruder* extruder() const
{
return m_extruder;
@@ -288,12 +282,12 @@ public:
return m_particleSizeVariation;
}
- QSGStochasticDirection * speed() const
+ QSGDirection * speed() const
{
return m_speed;
}
- QSGStochasticDirection * acceleration() const
+ QSGDirection * acceleration() const
{
return m_acceleration;
}
@@ -308,23 +302,18 @@ public:
return m_startTime;
}
- bool overwrite() const
- {
- return m_overwrite;
- }
-
protected:
qreal m_particlesPerSecond;
int m_particleDuration;
int m_particleDurationVariation;
- bool m_emitting;
+ bool m_enabled;
QSGParticleSystem* m_system;
QString m_particle;
QSGParticleExtruder* m_extruder;
QSGParticleExtruder* m_defaultExtruder;
QSGParticleExtruder* effectiveExtruder();
- QSGStochasticDirection * m_speed;
- QSGStochasticDirection * m_acceleration;
+ QSGDirection * m_speed;
+ QSGDirection * m_acceleration;
qreal m_particleSize;
qreal m_particleEndSize;
qreal m_particleSizeVariation;
@@ -340,7 +329,7 @@ protected:
//Used in default implementation, but might be useful
qreal m_speed_from_movement;
- int m_particle_count;
+ int m_emitCap;
bool m_reset_last;
qreal m_last_timestamp;
qreal m_last_emission;
@@ -351,7 +340,7 @@ protected:
bool isEmitConnected();
private:
- QSGStochasticDirection m_nullVector;
+ QSGDirection m_nullVector;
};
diff --git a/src/declarative/particles/qsgparticleextruder.cpp b/src/declarative/particles/qsgparticleextruder.cpp
index a390bb92ac..73c8ce0a66 100644
--- a/src/declarative/particles/qsgparticleextruder.cpp
+++ b/src/declarative/particles/qsgparticleextruder.cpp
@@ -52,30 +52,14 @@ QT_BEGIN_NAMESPACE
*/
QSGParticleExtruder::QSGParticleExtruder(QObject *parent) :
- QObject(parent), m_fill(true)
+ QObject(parent)
{
}
QPointF QSGParticleExtruder::extrude(const QRectF &rect)
{
- if (m_fill)
- return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
- ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
- int side = rand() % 4;
- switch (side){//TODO: Doesn't this overlap the corners?
- case 0:
- return QPointF(rect.x(),
- ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
- case 1:
- return QPointF(rect.width() + rect.x(),
- ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
- case 2:
- return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
- rect.y());
- default:
- return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
- rect.height() + rect.y());
- }
+ return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
+ ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
}
bool QSGParticleExtruder::contains(const QRectF &bounds, const QPointF &point)
diff --git a/src/declarative/particles/qsgparticleextruder_p.h b/src/declarative/particles/qsgparticleextruder_p.h
index bb2cc24ac2..b31b80231d 100644
--- a/src/declarative/particles/qsgparticleextruder_p.h
+++ b/src/declarative/particles/qsgparticleextruder_p.h
@@ -55,32 +55,15 @@ QT_MODULE(Declarative)
class QSGParticleExtruder : public QObject
{
Q_OBJECT
- Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)//###Should this be base class, or a BoxExtruder?
public:
explicit QSGParticleExtruder(QObject *parent = 0);
virtual QPointF extrude(const QRectF &);
- virtual bool contains(const QRectF &bounds, const QPointF &point);//###Needed for follow emitter, but does it belong? Only marginally conceptually valid, and that's from user's perspective
- bool fill() const
- {
- return m_fill;
- }
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
signals:
-
- void fillChanged(bool arg);
-
public slots:
-
- void setFill(bool arg)
- {
- if (m_fill != arg) {
- m_fill = arg;
- emit fillChanged(arg);
- }
- }
protected:
- bool m_fill;
};
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlepainter.cpp b/src/declarative/particles/qsgparticlepainter.cpp
index 97333ff20b..f4639c20a2 100644
--- a/src/declarative/particles/qsgparticlepainter.cpp
+++ b/src/declarative/particles/qsgparticlepainter.cpp
@@ -103,12 +103,16 @@ void QSGParticlePainter::setSystem(QSGParticleSystem *arg)
void QSGParticlePainter::load(QSGParticleData* d)
{
+ if (m_pleaseReset)
+ return;
initialize(d->group, d->index);
m_pendingCommits << qMakePair<int, int>(d->group, d->index);
}
void QSGParticlePainter::reload(QSGParticleData* d)
{
+ if (m_pleaseReset)
+ return;
m_pendingCommits << qMakePair<int, int>(d->group, d->index);
}
diff --git a/src/declarative/particles/qsgparticlesmodule.cpp b/src/declarative/particles/qsgparticlesmodule.cpp
index e6076b925f..9fa0ebad97 100644
--- a/src/declarative/particles/qsgparticlesmodule.cpp
+++ b/src/declarative/particles/qsgparticlesmodule.cpp
@@ -39,18 +39,17 @@
**
****************************************************************************/
-#include "qsgangleddirection_p.h"
+#include "qsgangledirection_p.h"
#include "qsgcustomparticle_p.h"
#include "qsgellipseextruder_p.h"
-#include "qsgfollowemitter_p.h"
+#include "qsgtrailemitter_p.h"
#include "qsgfriction_p.h"
#include "qsggravity_p.h"
#include "qsgimageparticle_p.h"
#include "qsgitemparticle_p.h"
-#include "qsgkill_p.h"
+#include "qsgage_p.h"
#include "qsglineextruder_p.h"
#include "qsgmaskextruder_p.h"
-#include "qsgmodelparticle_p.h"
#include "qsgparticleaffector_p.h"
#include "qsgparticleemitter_p.h"
#include "qsgparticleextruder_p.h"
@@ -60,12 +59,14 @@
#include "qsgpointattractor_p.h"
#include "qsgpointdirection_p.h"
#include "qsgspritegoal_p.h"
-#include "qsgstochasticdirection_p.h"
-#include "qsgtargeteddirection_p.h"
+#include "qsgdirection_p.h"
+#include "qsgtargetdirection_p.h"
#include "qsgturbulence_p.h"
#include "qsgwander_p.h"
#include "qsgtargetaffector_p.h"
#include "qsgcumulativedirection_p.h"
+#include "qsgcustomaffector_p.h"
+#include "qsgrectangleextruder_p.h"
QT_BEGIN_NAMESPACE
@@ -78,34 +79,35 @@ void QSGParticlesModule::defineModule()
qmlRegisterType<QSGImageParticle>(uri, 2, 0, "ImageParticle");
qmlRegisterType<QSGCustomParticle>(uri, 2, 0, "CustomParticle");
qmlRegisterType<QSGItemParticle>(uri, 2, 0, "ItemParticle");
- qmlRegisterType<QSGModelParticle>(uri, 2, 0, "ModelParticle");
qmlRegisterType<QSGParticleEmitter>(uri, 2, 0, "Emitter");
- qmlRegisterType<QSGFollowEmitter>(uri, 2, 0, "FollowEmitter");
+ qmlRegisterType<QSGTrailEmitter>(uri, 2, 0, "TrailEmitter");
qmlRegisterType<QSGEllipseExtruder>(uri, 2, 0, "EllipseShape");
+ qmlRegisterType<QSGRectangleExtruder>(uri, 2, 0, "RectangleShape");
qmlRegisterType<QSGLineExtruder>(uri, 2, 0, "LineShape");
qmlRegisterType<QSGMaskExtruder>(uri, 2, 0, "MaskShape");
qmlRegisterType<QSGPointDirection>(uri, 2, 0, "PointDirection");
- qmlRegisterType<QSGAngledDirection>(uri, 2, 0, "AngledDirection");
- qmlRegisterType<QSGTargetedDirection>(uri, 2, 0, "TargetedDirection");
+ qmlRegisterType<QSGAngleDirection>(uri, 2, 0, "AngleDirection");
+ qmlRegisterType<QSGTargetDirection>(uri, 2, 0, "TargetDirection");
qmlRegisterType<QSGCumulativeDirection>(uri, 2, 0, "CumulativeDirection");
- qmlRegisterType<QSGParticleAffector>(uri, 2, 0, "Affector");//useful for the triggered signal
+ qmlRegisterType<QSGCustomAffector>(uri, 2, 0, "Affector");
qmlRegisterType<QSGWanderAffector>(uri, 2, 0, "Wander");
qmlRegisterType<QSGFrictionAffector>(uri, 2, 0, "Friction");
- qmlRegisterType<QSGPointAttractorAffector>(uri, 2, 0, "PointAttractor");
+ qmlRegisterType<QSGAttractorAffector>(uri, 2, 0, "Attractor");
qmlRegisterType<QSGGravityAffector>(uri, 2, 0, "Gravity");
- qmlRegisterType<QSGKillAffector>(uri, 2, 0, "Kill");
+ qmlRegisterType<QSGAgeAffector>(uri, 2, 0, "Age");
qmlRegisterType<QSGSpriteGoalAffector>(uri, 2, 0, "SpriteGoal");
qmlRegisterType<QSGTurbulenceAffector>(uri, 2, 0 , "Turbulence");
qmlRegisterType<QSGTargetAffector>(uri, 2, 0 , "Target");
//Exposed just for completeness
- qmlRegisterType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter");
- qmlRegisterType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder");
- qmlRegisterType<QSGStochasticDirection>(uri, 2, 0, "NullVector");
+ qmlRegisterUncreatableType<QSGParticleAffector>(uri, 2, 0, "ParticleAffector", "Abstract type. Use one of the inheriting types instead.");
+ qmlRegisterUncreatableType<QSGParticlePainter>(uri, 2, 0, "ParticlePainter", "Abstract type. Use one of the inheriting types instead.");
+ qmlRegisterUncreatableType<QSGParticleExtruder>(uri, 2, 0, "ParticleExtruder", "Abstract type. Use one of the inheriting types instead.");
+ qmlRegisterUncreatableType<QSGDirection>(uri, 2, 0, "NullVector", "Abstract type. Use one of the inheriting types instead.");
}
QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgparticlesystem.cpp b/src/declarative/particles/qsgparticlesystem.cpp
index d12165e4e8..36cbd327ed 100644
--- a/src/declarative/particles/qsgparticlesystem.cpp
+++ b/src/declarative/particles/qsgparticlesystem.cpp
@@ -48,12 +48,14 @@
#include "qsgsprite_p.h"
#include "qsgv8particledata_p.h"
-#include "qsgfollowemitter_p.h"//###For auto-follow on states, perhaps should be in emitter?
+#include "qsgtrailemitter_p.h"//###For auto-follow on states, perhaps should be in emitter?
#include <private/qdeclarativeengine_p.h>
#include <cmath>
#include <QDebug>
QT_BEGIN_NAMESPACE
+//###Switch to define later, for now user-friendly (no compilation) debugging is worth it
+DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
/*!
\qmlclass ParticleSystem QSGParticleSystem
\inqmlmodule QtQuick.Particles 2
@@ -64,15 +66,38 @@ QT_BEGIN_NAMESPACE
/*!
\qmlproperty bool QtQuick.Particles2::ParticleSystem::running
- If running is set to false, the particle system will not advance the simulation.
+ If running is set to false, the particle system will stop the simulation. All particles
+ will be destroyed when the system is set to running again.
+
+ It can also be controlled with the start() and stop() methods.
+*/
+
+
+/*!
+ \qmlproperty bool QtQuick.Particles2::ParticleSystem::paused
+
+ If paused is set to true, the particle system will not advance the simulation. When
+ paused is set to false again, the simulation will resume from the same point it was
+ paused.
+
+ The simulation will automatically pause if it detects that there are no live particles
+ left, and unpause when new live particles are added.
+
+ It can also be controlled with the pause() and resume() methods.
*/
+
/*!
- \qmlproperty int QtQuick.Particles2::ParticleSystem::startTime
+ \qmlproperty bool QtQuick.Particles2::ParticleSystem::clear
+
+ clear is set to true when there are no live particles left in the system.
- If start time is specified, then the system will simulate up to this time
- before the system starts playing. This allows you to appear to start with a
- fully populated particle system, instead of starting with no particles visible.
+ You can use this to pause the system, keeping it from spending any time updating,
+ but you will need to resume it in order for additional particles to be generated
+ by the system.
+
+ To kill all the particles in the system, use a Kill affector.
*/
+
/*!
\qmlproperty list<Sprite> QtQuick.Particles2::ParticleSystem::particleStates
@@ -81,10 +106,55 @@ QT_BEGIN_NAMESPACE
Each QtQuick2::Sprite in this list is interpreted as corresponding to the particle group
with ths same name. Any transitions defined in these sprites will take effect on the particle
- groups as well. Additionally FollowEmitters, Affectors and ParticlePainters definined
+ groups as well. Additionally TrailEmitters, Affectors and ParticlePainters definined
inside one of these sprites are automatically associated with the corresponding particle group.
*/
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::pause
+
+ Pauses the simulation if it is running.
+
+ \sa resume, paused
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::resume
+
+ Resumes the simulation if it is paused.
+
+ \sa pause, paused
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::start
+
+ Starts the simulation if it has not already running.
+
+ \sa stop, restart, running
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::stop
+
+ Stops the simulation if it is running.
+
+ \sa start, restart, running
+*/
+
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::restart
+
+ Stops the simulation if it is running, and then starts it.
+
+ \sa stop, restart, running
+*/
+/*!
+ \qmlmethod void QtQuick.Particles2::ParticleSystem::reset
+
+ Discards all currently existing particles.
+
+*/
const qreal EPSILON = 0.001;
//Utility functions for when within 1ms is close enough
bool timeEqualOrGreater(qreal a, qreal b){
@@ -115,9 +185,13 @@ void QSGParticleDataHeap::grow() //###Consider automatic growth vs resize() call
m_data.resize(1 << ++m_size);
}
-void QSGParticleDataHeap::insert(QSGParticleData* data)//TODO: Optimize 0 lifespan (or already dead) case
+void QSGParticleDataHeap::insert(QSGParticleData* data)
{
- int time = roundedTime(data->t + data->lifeSpan);
+ insertTimed(data, roundedTime(data->t + data->lifeSpan));
+}
+
+void QSGParticleDataHeap::insertTimed(QSGParticleData* data, int time){
+ //TODO: Optimize 0 lifespan (or already dead) case
if (m_lookups.contains(time)){
m_data[m_lookups[time]].data << data;
return;
@@ -250,7 +324,8 @@ void QSGParticleGroupData::initList()
dataHeap.clear();
}
-void QSGParticleGroupData::kill(QSGParticleData* d){
+void QSGParticleGroupData::kill(QSGParticleData* d)
+{
Q_ASSERT(d->group == index);
d->lifeSpan = 0;//Kill off
foreach (QSGParticlePainter* p, painters)
@@ -258,21 +333,14 @@ void QSGParticleGroupData::kill(QSGParticleData* d){
reusableIndexes << d->index;
}
-QSGParticleData* QSGParticleGroupData::newDatum(bool respectsLimits){
- while (dataHeap.top() <= m_system->m_timeInt){
- foreach (QSGParticleData* datum, dataHeap.pop()){
- if (!datum->stillAlive()){
- reusableIndexes << datum->index;
- }else{
- prepareRecycler(datum); //ttl has been altered mid-way, put it back
- }
- }
- }
+QSGParticleData* QSGParticleGroupData::newDatum(bool respectsLimits)
+{
+ //recycle();//Extra recycler round to be sure?
while (!reusableIndexes.empty()){
int idx = *(reusableIndexes.begin());
reusableIndexes.remove(idx);
- if (data[idx]->stillAlive()){// ### This means resurrection of dead particles. Is that allowed?
+ if (data[idx]->stillAlive()){// ### This means resurrection of 'dead' particles. Is that allowed?
prepareRecycler(data[idx]);
continue;
}
@@ -287,8 +355,30 @@ QSGParticleData* QSGParticleGroupData::newDatum(bool respectsLimits){
return data[oldSize];
}
+bool QSGParticleGroupData::recycle()
+{
+ while (dataHeap.top() <= m_system->m_timeInt){
+ foreach (QSGParticleData* datum, dataHeap.pop()){
+ if (!datum->stillAlive()){
+ reusableIndexes << datum->index;
+ }else{
+ prepareRecycler(datum); //ttl has been altered mid-way, put it back
+ }
+ }
+ }
+
+ //TODO: If the data is clear, gc (consider shrinking stack size)?
+ return reusableIndexes.count() == m_size;
+}
+
void QSGParticleGroupData::prepareRecycler(QSGParticleData* d){
- dataHeap.insert(d);
+ if (d->lifeSpan*1000 < m_system->maxLife){
+ dataHeap.insert(d);
+ } else {
+ while ((roundedTime(d->t) + 2*m_system->maxLife/3) <= m_system->m_timeInt)
+ d->extendLife(m_system->maxLife/3000.0);
+ dataHeap.insertTimed(d, roundedTime(d->t) + 2*m_system->maxLife/3);
+ }
}
QSGParticleData::QSGParticleData(QSGParticleSystem* sys)
@@ -487,17 +577,36 @@ float QSGParticleData::lifeLeft()
return (t + lifeSpan) - (system->m_timeInt/1000.0);
}
-QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
- QSGItem(parent), m_particle_count(0), m_running(true)
- , m_startTime(0), m_nextIndex(0), m_componentComplete(false), m_spriteEngine(0)
+void QSGParticleData::extendLife(float time)
{
- QSGParticleGroupData* gd = new QSGParticleGroupData(0, this);//Default group
- m_groupData.insert(0,gd);
- m_groupIds.insert(QString(),0);
- m_nextGroupId = 1;
+ qreal newX = curX();
+ qreal newY = curY();
+ qreal newVX = curVX();
+ qreal newVY = curVY();
+
+ t += time;
+ animT += time;
+
+ qreal elapsed = (system->m_timeInt / 1000.0) - t;
+ qreal evy = newVY - elapsed*ay;
+ qreal ey = newY - elapsed*evy - 0.5 * elapsed*elapsed*ay;
+ qreal evx = newVX - elapsed*ax;
+ qreal ex = newX - elapsed*evx - 0.5 * elapsed*elapsed*ax;
+
+ x = ex;
+ vx = evx;
+ y = ey;
+ vy = evy;
+}
+QSGParticleSystem::QSGParticleSystem(QSGItem *parent) :
+ QSGItem(parent), m_particle_count(0), m_running(true), m_paused(false)
+ , m_nextIndex(0), m_componentComplete(false), m_spriteEngine(0)
+{
connect(&m_painterMapper, SIGNAL(mapped(QObject*)),
this, SLOT(loadPainter(QObject*)));
+
+ m_debugMode = qmlParticlesDebug();
}
QSGParticleSystem::~QSGParticleSystem()
@@ -506,7 +615,22 @@ QSGParticleSystem::~QSGParticleSystem()
delete gd;
}
-QDeclarativeListProperty<QSGSprite> QSGParticleSystem::particleStates()
+void QSGParticleSystem::initGroups()
+{
+ m_reusableIndexes.clear();
+ m_nextIndex = 0;
+
+ qDeleteAll(m_groupData);
+ m_groupData.clear();
+ m_groupIds.clear();
+
+ QSGParticleGroupData* gd = new QSGParticleGroupData(0, this);//Default group
+ m_groupData.insert(0,gd);
+ m_groupIds.insert("",0);
+ m_nextGroupId = 1;
+}
+
+ QDeclarativeListProperty<QSGSprite> QSGParticleSystem::particleStates()
{
return QDeclarativeListProperty<QSGSprite>(this, &m_states, spriteAppend, spriteCount, spriteAt, spriteClear);
}
@@ -514,11 +638,10 @@ QDeclarativeListProperty<QSGSprite> QSGParticleSystem::particleStates()
void QSGParticleSystem::registerParticlePainter(QSGParticlePainter* p)
{
//TODO: a way to Unregister emitters, painters and affectors
- m_particlePainters << QPointer<QSGParticlePainter>(p);//###Set or uniqueness checking?
+ m_painters << QPointer<QSGParticlePainter>(p);//###Set or uniqueness checking?
connect(p, SIGNAL(particlesChanged(QStringList)),
&m_painterMapper, SLOT(map()));
loadPainter(p);
- p->update();//###Initial update here?
}
void QSGParticleSystem::registerParticleEmitter(QSGParticleEmitter* e)
@@ -537,6 +660,121 @@ void QSGParticleSystem::registerParticleAffector(QSGParticleAffector* a)
m_affectors << QPointer<QSGParticleAffector>(a);
}
+void QSGParticleSystem::setRunning(bool arg)
+{
+ if (m_running != arg) {
+ m_running = arg;
+ emit runningChanged(arg);
+ setPaused(false);
+ if (m_animation)//Not created until componentCompleted
+ m_running ? m_animation->start() : m_animation->stop();
+ reset();
+ }
+}
+
+void QSGParticleSystem::setPaused(bool arg){
+ if (m_paused != arg) {
+ m_paused = arg;
+ if (m_animation && m_animation->state() != QAbstractAnimation::Stopped)
+ m_paused ? m_animation->pause() : m_animation->resume();
+ if (!m_paused){
+ foreach (QSGParticlePainter *p, m_painters)
+ p->update();
+ }
+ emit pausedChanged(arg);
+ }
+}
+
+void QSGParticleSystem::stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
+{
+ //Hooks up automatic state-associated stuff
+ QSGParticleSystem* sys = qobject_cast<QSGParticleSystem*>(prop->object->parent());
+ QSGSprite* sprite = qobject_cast<QSGSprite*>(prop->object);
+ if (!sprite || !sys)
+ return;
+ QStringList list;
+ list << sprite->name();
+ QSGParticleAffector* a = qobject_cast<QSGParticleAffector*>(value);
+ if (a){
+ a->setParentItem(sys);
+ a->setParticles(list);
+ a->setSystem(sys);
+ return;
+ }
+ QSGTrailEmitter* fe = qobject_cast<QSGTrailEmitter*>(value);
+ if (fe){
+ fe->setParentItem(sys);
+ fe->setFollow(sprite->name());
+ fe->setSystem(sys);
+ return;
+ }
+ QSGParticleEmitter* e = qobject_cast<QSGParticleEmitter*>(value);
+ if (e){
+ e->setParentItem(sys);
+ e->setParticle(sprite->name());
+ e->setSystem(sys);
+ return;
+ }
+ QSGParticlePainter* p = qobject_cast<QSGParticlePainter*>(value);
+ if (p){
+ p->setParentItem(sys);
+ p->setParticles(list);
+ p->setSystem(sys);
+ return;
+ }
+ qWarning() << value << " was placed inside a particle system state but cannot be taken into the particle system. It will be lost.";
+}
+
+void QSGParticleSystem::componentComplete()
+
+{
+ QSGItem::componentComplete();
+ m_componentComplete = true;
+ m_animation = new QSGParticleSystemAnimation(this);
+ reset();//restarts animation as well
+}
+
+void QSGParticleSystem::reset()
+{
+ if (!m_componentComplete)
+ return;
+
+ m_timeInt = 0;
+ //Clear guarded pointers which have been deleted
+ int cleared = 0;
+ cleared += m_emitters.removeAll(0);
+ cleared += m_painters.removeAll(0);
+ cleared += m_affectors.removeAll(0);
+
+ m_bySysIdx.resize(0);
+ initGroups();//Also clears all logical particles
+
+ if (!m_running)
+ return;
+
+ foreach (QSGParticleEmitter* e, m_emitters)
+ e->reset();
+
+ emittersChanged();
+
+ foreach (QSGParticlePainter *p, m_painters){
+ loadPainter(p);
+ p->reset();
+ }
+
+ //### Do affectors need reset too?
+
+ if (m_running) {//reset restarts animation (if running)
+ if ((m_animation->state() == QAbstractAnimation::Running))
+ m_animation->stop();
+ m_animation->start();
+ if (m_paused)
+ m_animation->pause();
+ }
+ m_initialized = true;
+}
+
+
void QSGParticleSystem::loadPainter(QObject *p)
{
if (!m_componentComplete)
@@ -566,7 +804,7 @@ void QSGParticleSystem::loadPainter(QObject *p)
}
}
painter->setCount(particleCount);
- painter->update();//###Initial update here?
+ painter->update();//Initial update here
return;
}
@@ -609,101 +847,14 @@ void QSGParticleSystem::emittersChanged()
Q_ASSERT(m_particle_count >= m_bySysIdx.size());//XXX when GC done right
m_bySysIdx.resize(m_particle_count);
- foreach (QSGParticlePainter *p, m_particlePainters)
+ foreach (QSGParticlePainter *p, m_painters)
loadPainter(p);
if (!m_states.isEmpty())
createEngine();
- if (m_particle_count > 16000)//###Investigate if these limits are worth warning about?
- qWarning() << "Particle system arbitarily believes it has a vast number of particles (>16000). Expect poor performance";
-}
-
-void QSGParticleSystem::setRunning(bool arg)
-{
- if (m_running != arg) {
- m_running = arg;
- emit runningChanged(arg);
- reset();
- }
-}
-
-void QSGParticleSystem::stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value)
-{
- //Hooks up automatic state-associated stuff
- QSGParticleSystem* sys = qobject_cast<QSGParticleSystem*>(prop->object->parent());
- QSGSprite* sprite = qobject_cast<QSGSprite*>(prop->object);
- if (!sprite || !sys)
- return;
- QStringList list;
- list << sprite->name();
- QSGParticleAffector* a = qobject_cast<QSGParticleAffector*>(value);
- if (a){
- a->setParentItem(sys);
- a->setParticles(list);
- a->setSystem(sys);
- return;
- }
- QSGFollowEmitter* e = qobject_cast<QSGFollowEmitter*>(value);
- if (e){
- e->setParentItem(sys);
- e->setFollow(sprite->name());
- e->setSystem(sys);
- return;
- }
- QSGParticlePainter* p = qobject_cast<QSGParticlePainter*>(value);
- if (p){
- p->setParentItem(sys);
- p->setParticles(list);
- p->setSystem(sys);
- return;
- }
- qWarning() << value << " was placed inside a particle system state but cannot be taken into the particle system. It will be lost.";
-}
-
-void QSGParticleSystem::componentComplete()
-
-{
- QSGItem::componentComplete();
- m_componentComplete = true;
- m_animation = new QSGParticleSystemAnimation(this);
- reset();//restarts animation as well
-}
-
-void QSGParticleSystem::reset()//TODO: Needed? Or just in component complete?
-{
- if (!m_componentComplete)
- return;
-
- m_timeInt = 0;
- //Clear guarded pointers which have been deleted
- int cleared = 0;
- cleared += m_emitters.removeAll(0);
- cleared += m_particlePainters.removeAll(0);
- cleared += m_affectors.removeAll(0);
-
- emittersChanged();
-
- //TODO: Reset data
-// foreach (QSGParticlePainter* p, m_particlePainters)
-// p->reset();
-// foreach (QSGParticleEmitter* e, m_emitters)
-// e->reset();
- //### Do affectors need reset too?
-
- if (!m_running)
- return;
-
- foreach (QSGParticlePainter *p, m_particlePainters){
- loadPainter(p);
- p->reset();
- }
-
- if (m_animation){
- m_animation->stop();
- m_animation->start();
- }
- m_initialized = true;
+ if (m_debugMode)
+ qDebug() << "Particle system emitters changed. New particle count: " << m_particle_count;
}
void QSGParticleSystem::createEngine()
@@ -815,6 +966,7 @@ QSGParticleData* QSGParticleSystem::newDatum(int groupId, bool respectLimits, in
if (m_spriteEngine)
m_spriteEngine->startSprite(ret->systemIndex, ret->group);
+ m_empty = false;
return ret;
}
@@ -844,17 +996,21 @@ void QSGParticleSystem::finishNewDatum(QSGParticleData *pd){
void QSGParticleSystem::updateCurrentTime( int currentTime )
{
- if (!m_running)
- return;
if (!m_initialized)
return;//error in initialization
//### Elapsed time never shrinks - may cause problems if left emitting for weeks at a time.
qreal dt = m_timeInt / 1000.;
- m_timeInt = currentTime + m_startTime;
+ m_timeInt = currentTime;
qreal time = m_timeInt / 1000.;
dt = time - dt;
m_needsReset.clear();
+
+ bool oldClear = m_empty;
+ m_empty = true;
+ foreach (QSGParticleGroupData* gd, m_groupData)//Recycle all groups and see if they're out of live particles
+ m_empty = m_empty && gd->recycle();
+
if (m_spriteEngine)
m_spriteEngine->updateSprites(m_timeInt);
@@ -868,6 +1024,9 @@ void QSGParticleSystem::updateCurrentTime( int currentTime )
foreach (QSGParticlePainter* p, m_groupData[d->group]->painters)
if (p && d)
p->reload(d);
+
+ if (oldClear != m_empty)
+ emptyChanged(m_empty);
}
int QSGParticleSystem::systemSync(QSGParticlePainter* p)
diff --git a/src/declarative/particles/qsgparticlesystem_p.h b/src/declarative/particles/qsgparticlesystem_p.h
index abb7f52c31..25a0c87f53 100644
--- a/src/declarative/particles/qsgparticlesystem_p.h
+++ b/src/declarative/particles/qsgparticlesystem_p.h
@@ -80,6 +80,7 @@ class QSGParticleDataHeap {
public:
QSGParticleDataHeap();
void insert(QSGParticleData* data);
+ void insertTimed(QSGParticleData* data, int time);
int top();
@@ -117,6 +118,7 @@ public:
QVector<QSGParticleData*> data;
QSGParticleDataHeap dataHeap;
QSet<int> reusableIndexes;
+ bool recycle(); //Force recycling round, reutrns true if all indexes are now reusable
void initList();
void kill(QSGParticleData* d);
@@ -210,6 +212,7 @@ public:
float curSize();
void clone(const QSGParticleData& other);//Not =, leaves meta-data like index
QDeclarativeV8Handle v8Value();
+ void extendLife(float time);
private:
QSGV8ParticleData* v8Datum;
};
@@ -218,7 +221,8 @@ class QSGParticleSystem : public QSGItem
{
Q_OBJECT
Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
- Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
Q_PROPERTY(QDeclarativeListProperty<QSGSprite> particleStates READ particleStates)
public:
@@ -232,38 +236,31 @@ public:
return m_running;
}
- int startTime() const
- {
- return m_startTime;
- }
-
int count(){ return m_particle_count; }
+ static const int maxLife = 600000;
+
signals:
void systemInitialized();
void runningChanged(bool arg);
-
- void startTimeChanged(int arg);
-
+ void pausedChanged(bool arg);
+ void emptyChanged(bool arg);
public slots:
+ void start(){setRunning(true);}
+ void stop(){setRunning(false);}
+ void restart(){setRunning(false);setRunning(true);}
+ void pause(){setPaused(true);}
+ void resume(){setPaused(false);}
+
void reset();
void setRunning(bool arg);
-
-
- void setStartTime(int arg)
- {
- m_startTime = arg;
- }
-
- void fastForward(int ms)
- {
- m_startTime += ms;
- }
+ void setPaused(bool arg);
virtual int duration() const { return -1; }
+
protected:
//This one only once per frame (effectively)
void componentComplete();
@@ -300,14 +297,24 @@ public://###but only really for related class usage. Perhaps we should all be fr
int m_particle_count;
static void stateRedirect(QDeclarativeListProperty<QObject> *prop, QObject *value);//From QSGSprite
+ bool isPaused() const
+ {
+ return m_paused;
+ }
+
+ bool isEmpty() const
+ {
+ return m_empty;
+ }
+
private:
void initializeSystem();
+ void initGroups();
bool m_running;
QList<QPointer<QSGParticleEmitter> > m_emitters;
QList<QPointer<QSGParticleAffector> > m_affectors;
- QList<QPointer<QSGParticlePainter> > m_particlePainters;
+ QList<QPointer<QSGParticlePainter> > m_painters;
QList<QPointer<QSGParticlePainter> > m_syncList;
- qint64 m_startTime;
int m_nextGroupId;
int m_nextIndex;
QSet<int> m_reusableIndexes;
@@ -319,6 +326,10 @@ private:
friend class QSGParticleSystemAnimation;
void updateCurrentTime( int currentTime );
QSGParticleSystemAnimation* m_animation;
+ bool m_paused;
+ bool m_debugMode;
+ bool m_allDead;
+ bool m_empty;
};
// Internally, this animation drives all the timing. Painters sync up in their updatePaintNode
diff --git a/src/declarative/particles/qsgpointattractor.cpp b/src/declarative/particles/qsgpointattractor.cpp
index 21eaeaac12..8c2632f2c8 100644
--- a/src/declarative/particles/qsgpointattractor.cpp
+++ b/src/declarative/particles/qsgpointattractor.cpp
@@ -44,24 +44,75 @@
#include <QDebug>
QT_BEGIN_NAMESPACE
/*!
- \qmlclass PointAttractor QSGPointAttractorAffector
+ \qmlclass Attractor QSGAttractorAffector
\inqmlmodule QtQuick.Particles 2
\inherits Affector
- \brief The PointAttractor allows you to attract particles towards a specific point.
+ \brief The Attractor allows you to attract particles towards a specific point.
Note that the size and position of this element affects which particles it affects.
The size of the point attracted to is always 0x0, and the location of that point
- is specified by the x and y properties that badly need renaming.
+ is specified by the pointX and pointY properties.
+ Note that Attractor has the standard Item x,y,width and height properties.
+ Like other affectors, these represent the affected area. They
+ do not represent the 0x0 point which is the target of the attraction.
+
+*/
+
+
+/*!
+ \qmlproperty real QtQuick.Particles2::PointAttractor::pointX
+
+ The x coordinate of the attracting point. This is relative
+ to the x coordinate of the Attractor.
*/
+/*!
+ \qmlproperty real QtQuick.Particles2::PointAttractor::pointY
+
+ The x coordinate of the attracting point. This is relative
+ to the x coordinate of the Attractor.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::PointAttractor::strength
+
+ The pull, in units per second, to be exerted on an item one pixel away.
+
+ Depending on how the attraction is proportionalToDistance this may have to
+ be very high or very low to have a reasonable effect on particles at a
+ distance.
+*/
+/*!
+ \qmlproperty AffectableParameter QtQuick.Particles2::Attractor::affectedParameter
+
+ What attribute of particles is directly affected.
+ \list
+ \o Attractor.Position
+ \o Attractor.Velocity
+ \o Attractor.Acceleration
+ \endlist
+*/
+/*!
+ \qmlproperty Proportion QtQuick.Particles2::Attractor::proportionalToDistance
+
+ 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
+ \endlist
+*/
+
-QSGPointAttractorAffector::QSGPointAttractorAffector(QSGItem *parent) :
+QSGAttractorAffector::QSGAttractorAffector(QSGItem *parent) :
QSGParticleAffector(parent), m_strength(0.0), m_x(0), m_y(0)
, m_physics(Velocity), m_proportionalToDistance(Linear)
{
}
-bool QSGPointAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
+bool QSGAttractorAffector::affectParticle(QSGParticleData *d, qreal dt)
{
if (m_strength == 0.0)
return false;
diff --git a/src/declarative/particles/qsgpointattractor_p.h b/src/declarative/particles/qsgpointattractor_p.h
index e2cdd0fdca..75dd47e331 100644
--- a/src/declarative/particles/qsgpointattractor_p.h
+++ b/src/declarative/particles/qsgpointattractor_p.h
@@ -49,15 +49,15 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGPointAttractorAffector : public QSGParticleAffector
+class QSGAttractorAffector : public QSGParticleAffector
{
Q_OBJECT
Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged)
Q_PROPERTY(qreal pointX READ pointX WRITE setPointX NOTIFY pointXChanged)
Q_PROPERTY(qreal pointY READ pointY WRITE setPointY NOTIFY pointYChanged)
- Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged)
+ Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
Q_PROPERTY(Proportion proportionalToDistance READ proportionalToDistance WRITE setProportionalToDistance NOTIFY proportionalToDistanceChanged)
- Q_ENUMS(PhysicsAffects)
+ Q_ENUMS(AffectableParameters)
Q_ENUMS(Proportion)
public:
@@ -69,13 +69,13 @@ public:
InverseQuadratic
};
- enum PhysicsAffects {
+ enum AffectableParameters {
Position,
Velocity,
Acceleration
};
- explicit QSGPointAttractorAffector(QSGItem *parent = 0);
+ explicit QSGAttractorAffector(QSGItem *parent = 0);
qreal strength() const
{
@@ -92,7 +92,7 @@ public:
return m_y;
}
- PhysicsAffects physics() const
+ AffectableParameters affectedParameter() const
{
return m_physics;
}
@@ -110,7 +110,7 @@ signals:
void pointYChanged(qreal arg);
- void physicsChanged(PhysicsAffects arg);
+ void affectedParameterChanged(AffectableParameters arg);
void proportionalToDistanceChanged(Proportion arg);
@@ -138,11 +138,11 @@ void setPointY(qreal arg)
emit pointYChanged(arg);
}
}
-void setPhysics(PhysicsAffects arg)
+void setAffectedParameter(AffectableParameters arg)
{
if (m_physics != arg) {
m_physics = arg;
- emit physicsChanged(arg);
+ emit affectedParameterChanged(arg);
}
}
@@ -160,7 +160,7 @@ private:
qreal m_strength;
qreal m_x;
qreal m_y;
-PhysicsAffects m_physics;
+AffectableParameters m_physics;
Proportion m_proportionalToDistance;
};
diff --git a/src/declarative/particles/qsgpointdirection.cpp b/src/declarative/particles/qsgpointdirection.cpp
index 7cc0823eec..dc104c1a81 100644
--- a/src/declarative/particles/qsgpointdirection.cpp
+++ b/src/declarative/particles/qsgpointdirection.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
/*!
\qmlclass PointDirection QSGPointDirection
\inqmlmodule QtQuick.Particles 2
- \inherits StochasticDirection
+ \inherits Direction
\brief The PointDirection element allows you to specify a direction that varies in x and y components
The PointDirection element allows both the specification of a direction by x and y components,
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
*/
QSGPointDirection::QSGPointDirection(QObject *parent) :
- QSGStochasticDirection(parent)
+ QSGDirection(parent)
, m_x(0)
, m_y(0)
, m_xVariation(0)
diff --git a/src/declarative/particles/qsgpointdirection_p.h b/src/declarative/particles/qsgpointdirection_p.h
index 6a6beb6623..ca00824a3e 100644
--- a/src/declarative/particles/qsgpointdirection_p.h
+++ b/src/declarative/particles/qsgpointdirection_p.h
@@ -41,7 +41,7 @@
#ifndef POINTVECTOR_H
#define POINTVECTOR_H
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
QT_BEGIN_HEADER
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGPointDirection : public QSGStochasticDirection
+class QSGPointDirection : public QSGDirection
{
Q_OBJECT
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
diff --git a/src/declarative/particles/qsgrectangleextruder.cpp b/src/declarative/particles/qsgrectangleextruder.cpp
new file mode 100644
index 0000000000..accc88fcdb
--- /dev/null
+++ b/src/declarative/particles/qsgrectangleextruder.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 "qsgrectangleextruder_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass RectangleShape QSGRectangleExtruder
+ \inqmlmodule QtQuick.Particles 2
+ \brief The RectangleShape element allows you to specify an area for affectors and emitter.
+
+ Just a rectangle.
+*/
+
+QSGRectangleExtruder::QSGRectangleExtruder(QObject *parent) :
+ QObject(parent), m_fill(true)
+{
+}
+
+QPointF QSGRectangleExtruder::extrude(const QRectF &rect)
+{
+ if (m_fill)
+ return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
+ ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
+ int side = rand() % 4;
+ switch (side){//TODO: Doesn't this overlap the corners?
+ case 0:
+ return QPointF(rect.x(),
+ ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
+ case 1:
+ return QPointF(rect.width() + rect.x(),
+ ((qreal)rand() / RAND_MAX) * rect.height() + rect.y());
+ case 2:
+ return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
+ rect.y());
+ default:
+ return QPointF(((qreal)rand() / RAND_MAX) * rect.width() + rect.x(),
+ rect.height() + rect.y());
+ }
+}
+
+bool QSGRectangleExtruder::contains(const QRectF &bounds, const QPointF &point)
+{
+ return bounds.contains(point);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgrectangleextruder_p.h b/src/declarative/particles/qsgrectangleextruder_p.h
new file mode 100644
index 0000000000..5795375c84
--- /dev/null
+++ b/src/declarative/particles/qsgrectangleextruder_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Declarative 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 RECTANGLEEXTRUDER_H
+#define RECTANGLEEXTRUDER_H
+
+#include "qsgparticleextruder_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QSGRectangleExtruder : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool fill READ fill WRITE setFill NOTIFY fillChanged)
+
+public:
+ explicit QSGRectangleExtruder(QObject *parent = 0);
+ virtual QPointF extrude(const QRectF &);
+ virtual bool contains(const QRectF &bounds, const QPointF &point);
+ bool fill() const
+ {
+ return m_fill;
+ }
+
+signals:
+
+ void fillChanged(bool arg);
+
+public slots:
+
+ void setFill(bool arg)
+ {
+ if (m_fill != arg) {
+ m_fill = arg;
+ emit fillChanged(arg);
+ }
+ }
+protected:
+ bool m_fill;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // RectangleEXTRUDER_H
diff --git a/src/declarative/particles/qsgtargeteddirection.cpp b/src/declarative/particles/qsgtargetdirection.cpp
index 696cdfa915..d9a3ce5a74 100644
--- a/src/declarative/particles/qsgtargeteddirection.cpp
+++ b/src/declarative/particles/qsgtargetdirection.cpp
@@ -39,41 +39,41 @@
**
****************************************************************************/
-#include "qsgtargeteddirection_p.h"
+#include "qsgtargetdirection_p.h"
#include "qsgparticleemitter_p.h"
#include <cmath>
#include <QDebug>
QT_BEGIN_NAMESPACE
/*!
- \qmlclass TargetedDirection QSGTargetedDirection
+ \qmlclass TargetDirection QSGTargetDirection
\inqmlmodule QtQuick.Particles 2
- \inherits StochasticDirection
- \brief The TargetedDirection element allows you to specify a direction towards the target point
+ \inherits Direction
+ \brief The TargetDirection element allows you to specify a direction towards the target point
*/
/*!
- \qmlproperty real QtQuick.Particles2::TargetedDirection::targetX
+ \qmlproperty real QtQuick.Particles2::TargetDirection::targetX
*/
/*!
- \qmlproperty real QtQuick.Particles2::TargetedDirection::targetY
+ \qmlproperty real QtQuick.Particles2::TargetDirection::targetY
*/
/*!
- \qmlproperty Item QtQuick.Particles2::TargetedDirection::targetItem
+ \qmlproperty Item QtQuick.Particles2::TargetDirection::targetItem
If specified, this will take precedence over targetX and targetY.
The targeted point will be the center of the specified Item
*/
/*!
- \qmlproperty real QtQuick.Particles2::TargetedDirection::targetVariation
+ \qmlproperty real QtQuick.Particles2::TargetDirection::targetVariation
*/
/*!
- \qmlproperty real QtQuick.Particles2::TargetedDirection::magnitude
+ \qmlproperty real QtQuick.Particles2::TargetDirection::magnitude
*/
/*!
- \qmlproperty real QtQuick.Particles2::TargetedDirection::magnitudeVariation
+ \qmlproperty real QtQuick.Particles2::TargetDirection::magnitudeVariation
*/
/*!
- \qmlproperty bool QtQuick.Particles2::TargetedDirection::proportionalMagnitude
+ \qmlproperty bool QtQuick.Particles2::TargetDirection::proportionalMagnitude
If true, then the value of magnitude and magnitudeVariation shall be interpreted as multiples
of the distance between the source point and the target point, per second.
@@ -82,8 +82,8 @@ QT_BEGIN_NAMESPACE
pixels per second.
*/
-QSGTargetedDirection::QSGTargetedDirection(QObject *parent) :
- QSGStochasticDirection(parent)
+QSGTargetDirection::QSGTargetDirection(QObject *parent) :
+ QSGDirection(parent)
, m_targetX(0)
, m_targetY(0)
, m_targetVariation(0)
@@ -94,7 +94,7 @@ QSGTargetedDirection::QSGTargetedDirection(QObject *parent) :
{
}
-const QPointF &QSGTargetedDirection::sample(const QPointF &from)
+const QPointF &QSGTargetDirection::sample(const QPointF &from)
{
//###This approach loses interpolating the last position of the target (like we could with the emitter) is it worthwhile?
qreal targetX;
diff --git a/src/declarative/particles/qsgtargeteddirection_p.h b/src/declarative/particles/qsgtargetdirection_p.h
index 6fdd3f937d..8f4901a57b 100644
--- a/src/declarative/particles/qsgtargeteddirection_p.h
+++ b/src/declarative/particles/qsgtargetdirection_p.h
@@ -41,7 +41,7 @@
#ifndef DIRECTEDVECTOR_H
#define DIRECTEDVECTOR_H
-#include "qsgstochasticdirection_p.h"
+#include "qsgdirection_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGItem;
-class QSGTargetedDirection : public QSGStochasticDirection
+class QSGTargetDirection : public QSGDirection
{
Q_OBJECT
Q_PROPERTY(qreal targetX READ targetX WRITE setTargetX NOTIFY targetXChanged)
@@ -65,7 +65,7 @@ class QSGTargetedDirection : public QSGStochasticDirection
Q_PROPERTY(qreal magnitudeVariation READ magnitudeVariation WRITE setMagnitudeVariation NOTIFY magnitudeVariationChanged)
public:
- explicit QSGTargetedDirection(QObject *parent = 0);
+ explicit QSGTargetDirection(QObject *parent = 0);
virtual const QPointF &sample(const QPointF &from);
qreal targetX() const
diff --git a/src/declarative/particles/qsgfollowemitter.cpp b/src/declarative/particles/qsgtrailemitter.cpp
index d2e3265e2d..6bccf3ba8c 100644
--- a/src/declarative/particles/qsgfollowemitter.cpp
+++ b/src/declarative/particles/qsgtrailemitter.cpp
@@ -39,21 +39,20 @@
**
****************************************************************************/
-#include "qsgfollowemitter_p.h"
-#include "qsgparticlepainter_p.h"//TODO: What was this for again?
+#include "qsgtrailemitter_p.h"
#include <cmath>
QT_BEGIN_NAMESPACE
/*!
- \qmlclass FollowEmitter QSGFollowEmitter
+ \qmlclass TrailEmitter QSGTrailEmitter
\inqmlmodule QtQuick.Particles 2
\inherits QSGParticleEmitter
- \brief The FollowEmitter element allows you to emit logical particles from other logical particles.
+ \brief The TrailEmitter element allows you to emit logical particles from other logical particles.
This element emits logical particles into the ParticleSystem, with the
starting positions based on those of other logical particles.
*/
-QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
+QSGTrailEmitter::QSGTrailEmitter(QSGItem *parent) :
QSGParticleEmitter(parent)
, m_particlesPerParticlePerSecond(0)
, m_lastTimeStamp(0)
@@ -73,28 +72,37 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
}
/*!
- \qmlproperty string QtQuick.Particles2::FollowEmitter::follow
+ \qmlproperty string QtQuick.Particles2::TrailEmitter::follow
The type of logical particle which this is emitting from.
*/
+/*!
+ \qmlproperty qreal QtQuick.Particles2::TrailEmitter::speedFromMovement
+
+ If this value is non-zero, then any movement of the emitter will provide additional
+ starting velocity to the particles based on the movement. The additional vector will be the
+ same angle as the emitter's movement, with a magnitude that is the magnitude of the emitters
+ movement multiplied by speedFromMovement.
+ Default value is 0.
+*/
/*!
- \qmlproperty Shape QtQuick.Particles2::FollowEmitter::emitShape
+ \qmlproperty Shape QtQuick.Particles2::TrailEmitter::emitShape
- As the area of a FollowEmitter is the area it follows, a separate shape can be provided
+ As the area of a TrailEmitter is the area it follows, a separate shape can be provided
to be the shape it emits out of.
*/
/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::emitWidth
+ \qmlproperty real QtQuick.Particles2::TrailEmitter::emitWidth
*/
/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::emitHeight
+ \qmlproperty real QtQuick.Particles2::TrailEmitter::emitHeight
*/
/*!
- \qmlproperty real QtQuick.Particles2::FollowEmitter::emitRatePerParticle
+ \qmlproperty real QtQuick.Particles2::TrailEmitter::emitRatePerParticle
*/
/*!
- \qmlsignal QtQuick.Particles2::FollowEmitter::emitFollowParticle(particle, followed)
+ \qmlsignal QtQuick.Particles2::TrailEmitter::emitFollowParticle(particle, followed)
This handler is called when a particle is emitted. You can modify particle
attributes from within the handler. followed is the particle that this is being
@@ -103,13 +111,13 @@ QSGFollowEmitter::QSGFollowEmitter(QSGItem *parent) :
If you use this signal handler, emitParticle will not be emitted.
*/
-bool QSGFollowEmitter::isEmitFollowConnected()
+bool QSGTrailEmitter::isEmitFollowConnected()
{
static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticle(QDeclarativeV8Handle,QDeclarativeV8Handle)");
return QObjectPrivate::get(this)->isSignalConnected(idx);
}
-void QSGFollowEmitter::recalcParticlesPerSecond(){
+void QSGTrailEmitter::recalcParticlesPerSecond(){
if (!m_system)
return;
m_followCount = m_system->m_groupData[m_system->m_groupIds[m_follow]]->size();
@@ -122,16 +130,16 @@ void QSGFollowEmitter::recalcParticlesPerSecond(){
}
}
-void QSGFollowEmitter::reset()
+void QSGTrailEmitter::reset()
{
m_followCount = 0;
}
-void QSGFollowEmitter::emitWindow(int timeStamp)
+void QSGTrailEmitter::emitWindow(int timeStamp)
{
if (m_system == 0)
return;
- if (!m_emitting && !m_burstLeft && m_burstQueue.isEmpty())
+ if (!m_enabled && !m_burstLeft && m_burstQueue.isEmpty())
return;
if (m_followCount != m_system->m_groupData[m_system->m_groupIds[m_follow]]->size()){
qreal oldPPS = m_particlesPerSecond;
@@ -209,7 +217,7 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
const QPointF &speed = m_speed->sample(newPos);
datum->vx = speed.x()
+ m_speed_from_movement * d->vx;
- datum->vy = speed.y()
+ datum->vy = speed.y();
+ m_speed_from_movement * d->vy;
// Particle acceleration
@@ -224,8 +232,8 @@ void QSGFollowEmitter::emitWindow(int timeStamp)
float size = qMax((qreal)0.0, m_particleSize + sizeVariation);
float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation);
- datum->size = size * float(m_emitting);
- datum->endSize = endSize * float(m_emitting);
+ datum->size = size * float(m_enabled);
+ datum->endSize = endSize * float(m_enabled);
if (isEmitFollowConnected())
emitFollowParticle(datum->v8Value(), d->v8Value());//A chance for many arbitrary JS changes
diff --git a/src/declarative/particles/qsgfollowemitter_p.h b/src/declarative/particles/qsgtrailemitter_p.h
index d26435df6a..5ab6f24270 100644
--- a/src/declarative/particles/qsgfollowemitter_p.h
+++ b/src/declarative/particles/qsgtrailemitter_p.h
@@ -51,21 +51,20 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class QSGFollowEmitter : public QSGParticleEmitter
+class QSGTrailEmitter : public QSGParticleEmitter
{
Q_OBJECT
Q_PROPERTY(QString follow READ follow WRITE setFollow NOTIFY followChanged)
- //### Remove, and just document that particles per second is per particle? But has count issues
Q_PROPERTY(int emitRatePerParticle READ particlesPerParticlePerSecond WRITE setParticlesPerParticlePerSecond NOTIFY particlesPerParticlePerSecondChanged)
- //TODO: Document that FollowEmitter's box is where it follows. It emits in a rect centered on the followed particle
+ //TODO: Document that TrailEmitter's box is where it follows. It emits in a rect centered on the followed particle
//TODO: A set of properties that can involve the particle size of the followed
Q_PROPERTY(QSGParticleExtruder* emitShape READ emissonShape WRITE setEmissionShape NOTIFY emissionShapeChanged)
Q_PROPERTY(qreal emitHeight READ emitterYVariation WRITE setEmitterYVariation NOTIFY emitterYVariationChanged)
Q_PROPERTY(qreal emitWidth READ emitterXVariation WRITE setEmitterXVariation NOTIFY emitterXVariationChanged)
public:
- explicit QSGFollowEmitter(QSGItem *parent = 0);
+ explicit QSGTrailEmitter(QSGItem *parent = 0);
virtual void emitWindow(int timeStamp);
virtual void reset();
diff --git a/src/declarative/particles/qsgturbulence.cpp b/src/declarative/particles/qsgturbulence.cpp
index 003f3c12b6..2caebc7c1f 100644
--- a/src/declarative/particles/qsgturbulence.cpp
+++ b/src/declarative/particles/qsgturbulence.cpp
@@ -138,7 +138,7 @@ void QSGTurbulenceAffector::mapUpdate()
void QSGTurbulenceAffector::affectSystem(qreal dt)
{
- if (!m_system || !m_active)
+ if (!m_system || !m_enabled)
return;
ensureInit();
qreal period = 1.0/m_frequency;
diff --git a/src/declarative/particles/qsgv8particledata.cpp b/src/declarative/particles/qsgv8particledata.cpp
index 72c0b7c2de..d45093c57e 100644
--- a/src/declarative/particles/qsgv8particledata.cpp
+++ b/src/declarative/particles/qsgv8particledata.cpp
@@ -128,7 +128,7 @@ static void particleData_set_ ## VARIABLE (v8::Local<v8::String>, v8::Local<v8::
r->datum-> SETTER ( value->NumberValue() );\
}
-#define FLOAT_REGISTER_ACCESSOR(FT, ENGINE, VARIABLE) FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), particleData_get_ ## VARIABLE , particleData_set_ ## VARIABLE , v8::External::Wrap(ENGINE))
+#define FLOAT_REGISTER_ACCESSOR(FT, ENGINE, VARIABLE, NAME) FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #NAME ), particleData_get_ ## VARIABLE , particleData_set_ ## VARIABLE , v8::External::Wrap(ENGINE))
FLOAT_GETTER_AND_SETTER(x)
FLOAT_GETTER_AND_SETTER(y)
@@ -169,34 +169,34 @@ QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
ft->InstanceTemplate()->SetHasExternalResource(true);
ft->PrototypeTemplate()->Set(v8::String::New("discard"), V8FUNCTION(particleData_discard, engine));
ft->PrototypeTemplate()->Set(v8::String::New("lifeLeft"), V8FUNCTION(particleData_lifeLeft, engine));
- ft->PrototypeTemplate()->Set(v8::String::New("curSize"), V8FUNCTION(particleData_curSize, engine));
- FLOAT_REGISTER_ACCESSOR(ft, engine, x);
- FLOAT_REGISTER_ACCESSOR(ft, engine, y);
- FLOAT_REGISTER_ACCESSOR(ft, engine, t);
- FLOAT_REGISTER_ACCESSOR(ft, engine, lifeSpan);
- FLOAT_REGISTER_ACCESSOR(ft, engine, size);
- FLOAT_REGISTER_ACCESSOR(ft, engine, endSize);
- FLOAT_REGISTER_ACCESSOR(ft, engine, vx);
- FLOAT_REGISTER_ACCESSOR(ft, engine, vy);
- FLOAT_REGISTER_ACCESSOR(ft, engine, ax);
- FLOAT_REGISTER_ACCESSOR(ft, engine, ay);
- FLOAT_REGISTER_ACCESSOR(ft, engine, xx);
- FLOAT_REGISTER_ACCESSOR(ft, engine, xy);
- FLOAT_REGISTER_ACCESSOR(ft, engine, rotation);
- FLOAT_REGISTER_ACCESSOR(ft, engine, rotationSpeed);
- FLOAT_REGISTER_ACCESSOR(ft, engine, autoRotate);
- FLOAT_REGISTER_ACCESSOR(ft, engine, animIdx);
- FLOAT_REGISTER_ACCESSOR(ft, engine, frameDuration);
- FLOAT_REGISTER_ACCESSOR(ft, engine, frameCount);
- FLOAT_REGISTER_ACCESSOR(ft, engine, animT);
- FLOAT_REGISTER_ACCESSOR(ft, engine, r);
- FLOAT_REGISTER_ACCESSOR(ft, engine, update);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curX);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curVX);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curAX);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curY);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curVY);
- FLOAT_REGISTER_ACCESSOR(ft, engine, curAY);
+ ft->PrototypeTemplate()->Set(v8::String::New("currentSize"), V8FUNCTION(particleData_curSize, engine));
+ FLOAT_REGISTER_ACCESSOR(ft, engine, x, initialX);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, y, initialY);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, t, t);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, lifeSpan, lifeSpan);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, size, startSize);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, endSize, endSize);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, vx, initialVX);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, vy, initialVY);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, ax, initialAX);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, ay, initialAY);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, xx, xDeformationVector);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, xy, yDeformationVector);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, rotation, rotation);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, rotationSpeed, rotationSpeed);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, autoRotate, autoRotate);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, animIdx, animationIndex);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, frameDuration, frameDuration);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, frameCount, frameCount);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, animT, animationT);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, r, r);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, update, update);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curX, x);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curVX, vx);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curAX, ax);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curY, y);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curVY, vy);
+ FLOAT_REGISTER_ACCESSOR(ft, engine, curAY, ay);
constructor = qPersistentNew(ft->GetFunction());
}
diff --git a/src/declarative/particles/qsgwander.cpp b/src/declarative/particles/qsgwander.cpp
index a4a4d2c9c5..d3e87fb241 100644
--- a/src/declarative/particles/qsgwander.cpp
+++ b/src/declarative/particles/qsgwander.cpp
@@ -49,10 +49,39 @@ QT_BEGIN_NAMESPACE
\brief The Wander affector allows particles to randomly vary their trajectory.
*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Wander::pace
+
+ Maximum attribute change per second.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Wander::xVariance
+
+ Maximum attribute x value (as a result of Wander).
+
+ If unset, Wander will not affect x values.
+*/
+/*!
+ \qmlproperty real QtQuick.Particles2::Wander::yVariance
+
+ Maximum attribute y value (as a result of Wander).
+
+ If unset, Wander will not affect y values.
+*/
+/*!
+ \qmlproperty AffectableParameter QtQuick.Particles2::Wander::affectedParameter
+
+ What attribute of particles is directly affected.
+ \list
+ \o PointAttractor.Position
+ \o PointAttractor.Velocity
+ \o PointAttractor.Acceleration
+ \endlist
+*/
QSGWanderAffector::QSGWanderAffector(QSGItem *parent) :
QSGParticleAffector(parent), m_xVariance(0), m_yVariance(0), m_pace(0)
- , m_physics(Velocity)
+ , m_affectedParameter(Velocity)
{
m_needsReset = true;
}
@@ -119,7 +148,7 @@ bool QSGWanderAffector::affectParticle(QSGParticleData* data, qreal dt)
qreal dx = dt * m_pace * (2 * qreal(qrand())/RAND_MAX - 1);
qreal dy = dt * m_pace * (2 * qreal(qrand())/RAND_MAX - 1);
qreal newX, newY;
- switch (m_physics){
+ switch (m_affectedParameter){
case Position:
newX = data->curX() + dx;
if (m_xVariance > qAbs(newX) )
diff --git a/src/declarative/particles/qsgwander_p.h b/src/declarative/particles/qsgwander_p.h
index ae98cf3681..46ad6ea3a2 100644
--- a/src/declarative/particles/qsgwander_p.h
+++ b/src/declarative/particles/qsgwander_p.h
@@ -66,11 +66,11 @@ class QSGWanderAffector : public QSGParticleAffector
Q_PROPERTY(qreal pace READ pace WRITE setPace NOTIFY paceChanged)
Q_PROPERTY(qreal xVariance READ xVariance WRITE setXVariance NOTIFY xVarianceChanged)
Q_PROPERTY(qreal yVariance READ yVariance WRITE setYVariance NOTIFY yVarianceChanged)
- Q_PROPERTY(PhysicsAffects physics READ physics WRITE setPhysics NOTIFY physicsChanged)
- Q_ENUMS(PhysicsAffects)
+ Q_PROPERTY(AffectableParameters affectedParameter READ affectedParameter WRITE setAffectedParameter NOTIFY affectedParameterChanged)
+ Q_ENUMS(AffectableParameters)
public:
- enum PhysicsAffects {
+ enum AffectableParameters {
Position,
Velocity,
Acceleration
@@ -95,9 +95,9 @@ public:
return m_pace;
}
- PhysicsAffects physics() const
+ AffectableParameters affectedParameter() const
{
- return m_physics;
+ return m_affectedParameter;
}
protected:
@@ -111,7 +111,7 @@ signals:
void paceChanged(qreal arg);
- void physicsChanged(PhysicsAffects arg);
+ void affectedParameterChanged(AffectableParameters arg);
public slots:
void setXVariance(qreal arg)
@@ -139,11 +139,11 @@ void setPace(qreal arg)
}
-void setPhysics(PhysicsAffects arg)
+void setAffectedParameter(AffectableParameters arg)
{
- if (m_physics != arg) {
- m_physics = arg;
- emit physicsChanged(arg);
+ if (m_affectedParameter != arg) {
+ m_affectedParameter = arg;
+ emit affectedParameterChanged(arg);
}
}
@@ -153,7 +153,7 @@ private:
qreal m_xVariance;
qreal m_yVariance;
qreal m_pace;
- PhysicsAffects m_physics;
+ AffectableParameters m_affectedParameter;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/ftw/qdeclarativepool.cpp b/src/declarative/qml/ftw/qdeclarativepool.cpp
index 94bb89bd46..7a28d92663 100644
--- a/src/declarative/qml/ftw/qdeclarativepool.cpp
+++ b/src/declarative/qml/ftw/qdeclarativepool.cpp
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
**
**
diff --git a/src/declarative/qml/ftw/qdeclarativepool_p.h b/src/declarative/qml/ftw/qdeclarativepool_p.h
index c4393fe2e6..60ff4fa359 100644
--- a/src/declarative/qml/ftw/qdeclarativepool_p.h
+++ b/src/declarative/qml/ftw/qdeclarativepool_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
**
**
diff --git a/src/declarative/qml/ftw/qdeclarativeutils_p.h b/src/declarative/qml/ftw/qdeclarativeutils_p.h
index 63e90012c2..ec19d9cf23 100644
--- a/src/declarative/qml/ftw/qdeclarativeutils_p.h
+++ b/src/declarative/qml/ftw/qdeclarativeutils_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
**
**
diff --git a/src/declarative/qml/ftw/qfieldlist_p.h b/src/declarative/qml/ftw/qfieldlist_p.h
index 65b1d4b4ee..ff6b89b96f 100644
--- a/src/declarative/qml/ftw/qfieldlist_p.h
+++ b/src/declarative/qml/ftw/qfieldlist_p.h
@@ -7,29 +7,29 @@
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** 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.
**
**
**
diff --git a/src/declarative/qml/ftw/qmetaobjectbuilder.cpp b/src/declarative/qml/ftw/qmetaobjectbuilder.cpp
index f5e8369ebc..e52b9e1172 100644
--- a/src/declarative/qml/ftw/qmetaobjectbuilder.cpp
+++ b/src/declarative/qml/ftw/qmetaobjectbuilder.cpp
@@ -155,6 +155,7 @@ struct QMetaObjectPrivate
int enumeratorCount, enumeratorData;
int constructorCount, constructorData;
int flags;
+ int signalCount;
};
static inline const QMetaObjectPrivate *priv(const uint* data)
@@ -1206,7 +1207,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
QMetaObjectPrivate *pmeta
= reinterpret_cast<QMetaObjectPrivate *>(buf + size);
int pmetaSize = size;
- dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
+ dataIndex = 14; // Number of fields in the QMetaObjectPrivate.
for (index = 0; index < d->properties.size(); ++index) {
if (d->properties[index].notifySignal != -1) {
hasNotifySignals = true;
@@ -1214,9 +1215,10 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
}
if (buf) {
- pmeta->revision = 3;
+ pmeta->revision = 4;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
+ //pmeta->signalCount is handled in the "output method loop" as an optimization.
pmeta->classInfoCount = d->classInfoNames.size();
pmeta->classInfoData = dataIndex;
@@ -1274,7 +1276,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
}
// Reset the current data position to just past the QMetaObjectPrivate.
- dataIndex = 13;
+ dataIndex = 14;
// Add the class name to the string table.
int offset = 0;
@@ -1312,6 +1314,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
data[dataIndex + 2] = ret;
data[dataIndex + 3] = tag;
data[dataIndex + 4] = attrs;
+ if (method->methodType() == QMetaMethod::Signal)
+ pmeta->signalCount++;
}
dataIndex += 5;
}
diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h
index a0eb98d366..312aecbf76 100644
--- a/src/declarative/qml/qdeclarative.h
+++ b/src/declarative/qml/qdeclarative.h
@@ -552,17 +552,6 @@ inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMi
return QDeclarativePrivate::qmlregister(QDeclarativePrivate::ModuleApiRegistration, &api);
}
-// Enable debugging before any QDeclarativeEngine is created
-struct Q_DECLARATIVE_EXPORT QDeclarativeDebuggingEnabler
-{
- QDeclarativeDebuggingEnabler();
-};
-
-// Execute code in constructor before first QDeclarativeEngine is instantiated
-#if defined(QT_DECLARATIVE_DEBUG)
-static QDeclarativeDebuggingEnabler qmlEnableDebuggingHelper;
-#endif
-
QT_END_NAMESPACE
QML_DECLARE_TYPE(QObject)
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index d817990d7b..9a69a6bfd0 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -243,6 +243,8 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont
cdata = typeData->compiledData();
}
QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding(cdata->primitives.at(id), true, obj, ctxtdata, url, lineNumber, parent) : 0;
+ if (cdata)
+ cdata->release();
if (typeData)
typeData->release();
return rv;
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index b01892813f..d5a55fed24 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -53,7 +53,7 @@
#include "private/qdeclarativeglobal_p.h"
#include "private/qdeclarativescript_p.h"
#include "private/qdeclarativedebugtrace_p.h"
-#include "private/qdeclarativeenginedebug_p.h"
+#include "private/qdeclarativeenginedebugservice_p.h"
#include "private/qv8engine_p.h"
#include "private/qv8include_p.h"
@@ -951,7 +951,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon
if (enginePriv->isDebugging && rv) {
if (!parentContext->isInternal)
parentContext->asQDeclarativeContextPrivate()->instances.append(rv);
- QDeclarativeEngineDebugServer::instance()->objectCreated(parentContext->engine, rv);
+ QDeclarativeEngineDebugService::instance()->objectCreated(parentContext->engine, rv);
if (isRoot) {
QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, buildTypeNameForDebug(rv->metaObject()));
QDeclarativeData *data = QDeclarativeData::get(rv);
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 353a86ca7a..4f31bc1a94 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -50,7 +50,7 @@
#include "qdeclarativecomponent.h"
#include "private/qdeclarativebinding_p_p.h"
#include "private/qdeclarativevme_p.h"
-#include "private/qdeclarativeenginedebug_p.h"
+#include "private/qdeclarativeenginedebugservice_p.h"
#include "private/qdeclarativestringconverters_p.h"
#include "private/qdeclarativexmlhttprequest_p.h"
#include "private/qdeclarativesqldatabase_p.h"
@@ -447,9 +447,9 @@ void QDeclarativeEnginePrivate::init()
rootContext = new QDeclarativeContext(q,true);
if (QCoreApplication::instance()->thread() == q->thread() &&
- QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
+ QDeclarativeEngineDebugService::isDebuggingEnabled()) {
isDebugging = true;
- QDeclarativeEngineDebugServer::instance()->addEngine(q);
+ QDeclarativeEngineDebugService::instance()->addEngine(q);
QV8DebugService::instance()->addEngine(q);
}
}
@@ -514,7 +514,7 @@ QDeclarativeEngine::~QDeclarativeEngine()
{
Q_D(QDeclarativeEngine);
if (d->isDebugging)
- QDeclarativeEngineDebugServer::instance()->remEngine(this);
+ QDeclarativeEngineDebugService::instance()->remEngine(this);
// if we are the parent of any of the qobject module api instances,
// we need to remove them from our internal list, in order to prevent
@@ -662,6 +662,8 @@ void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativ
/*!
Returns the QDeclarativeImageProvider set for \a providerId.
+
+ Returns the provider if it was found; otherwise returns 0.
*/
QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
{
@@ -673,8 +675,6 @@ QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &prov
/*!
Removes the QDeclarativeImageProvider for \a providerId.
- Returns the provider if it was found; otherwise returns 0.
-
\sa addImageProvider()
*/
void QDeclarativeEngine::removeImageProvider(const QString &providerId)
@@ -947,8 +947,10 @@ QDeclarativeContext *qmlContext(const QObject *obj)
QDeclarativeEngine *qmlEngine(const QObject *obj)
{
- QDeclarativeContext *context = QDeclarativeEngine::contextForObject(obj);
- return context?context->engine():0;
+ QDeclarativeData *data = QDeclarativeData::get(obj, false);
+ if (!data || !data->context)
+ return 0;
+ return data->context->engine;
}
QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
@@ -1680,4 +1682,20 @@ bool QDeclarative_isFileCaseCorrect(const QString &fileName)
return true;
}
+/*!
+ \fn QDeclarativeEngine *qmlEngine(const QObject *object)
+ \relates QDeclarativeEngine
+
+ Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
+ QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
+*/
+
+/*!
+ \fn QDeclarativeContext *qmlContext(const QObject *object)
+ \relates QDeclarativeEngine
+
+ Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
+ QDeclarativeEngine::contextForObject(object).
+*/
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h
index 3f90296681..74c3c6cb83 100644
--- a/src/declarative/qml/qdeclarativeengine.h
+++ b/src/declarative/qml/qdeclarativeengine.h
@@ -48,6 +48,7 @@
#include <QtDeclarative/qjsengine.h>
#include <QtDeclarative/qjsvalue.h>
#include <QtDeclarative/qdeclarativeerror.h>
+#include <QtDeclarative/qdeclarativedebug.h>
QT_BEGIN_HEADER
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index a24d46914c..4f6a71911f 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -256,6 +256,8 @@ QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &s
else
defaultConstruction = true;
+ if (cdata)
+ cdata->release();
if (typeData)
typeData->release();
}
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 406e43fc21..e35fa52eed 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -313,10 +313,14 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
allowedRevisionCache.append(0);
int methodCount = metaObject->methodCount();
+ Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
+ int signalCount = QMetaObjectPrivate::get(metaObject)->signalCount;
// 3 to block the destroyed signal and the deleteLater() slot
int methodOffset = qMax(3, metaObject->methodOffset());
methodIndexCache.resize(methodCount - methodIndexCacheStart);
+ signalHandlerIndexCache.resize(signalCount);
+ int signalHandlerIndex = 0;
for (int ii = methodOffset; ii < methodCount; ++ii) {
QMetaMethod m = metaObject->method(ii);
if (m.access() == QMetaMethod::Private)
@@ -329,6 +333,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
while (*cptr != '(') { Q_ASSERT(*cptr != 0); utf8 |= *cptr & 0x80; ++cptr; }
Data *data = &methodIndexCache[ii - methodIndexCacheStart];
+ Data *sigdata = 0;
data->lazyLoad(m);
@@ -342,6 +347,12 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->metaObjectOffset = allowedRevisionCache.count() - 1;
+ if (data->isSignal()) {
+ sigdata = &signalHandlerIndexCache[signalHandlerIndex];
+ *sigdata = *data;
+ sigdata->flags |= Data::IsSignalHandler;
+ }
+
Data *old = 0;
if (utf8) {
@@ -349,11 +360,33 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
if (Data **it = stringCache.value(methodName))
old = *it;
stringCache.insert(methodName, data);
+
+ if (data->isSignal()) {
+ QHashedString on(QStringLiteral("on") % methodName.at(0).toUpper() % methodName.midRef(1));
+ stringCache.insert(on, sigdata);
+ ++signalHandlerIndex;
+ }
} else {
QHashedCStringRef methodName(signature, cptr - signature);
if (Data **it = stringCache.value(methodName))
old = *it;
stringCache.insert(methodName, data);
+
+ if (data->isSignal()) {
+ int length = methodName.length();
+
+ QVarLengthArray<char, 128> str(length+3);
+ str[0] = 'o';
+ str[1] = 'n';
+ str[2] = toupper(signature[0]);
+ if (length > 1)
+ memcpy(&str[3], &signature[1], length - 1);
+ str[length + 2] = '\0';
+
+ QHashedString on(QString::fromLatin1(str.data()));
+ stringCache.insert(on, sigdata);
+ ++signalHandlerIndex;
+ }
}
if (old) {
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 8a1da1929c..33565c4d45 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -104,9 +104,10 @@ public:
IsSignal = 0x00008000, // Function is a signal
IsVMESignal = 0x00010000, // Signal was added by QML
IsV8Function = 0x00020000, // Function takes QDeclarativeV8Function* args
+ IsSignalHandler = 0x00040000, // Function is a signal handler
// Internal QDeclarativePropertyCache flags
- NotFullyResolved = 0x00040000 // True if the type data is to be lazily resolved
+ NotFullyResolved = 0x00080000 // True if the type data is to be lazily resolved
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -133,6 +134,7 @@ public:
bool isSignal() const { return flags & IsSignal; }
bool isVMESignal() const { return flags & IsVMESignal; }
bool isV8Function() const { return flags & IsV8Function; }
+ bool isSignalHandler() const { return flags & IsSignalHandler; }
union {
int propType; // When !NotFullyResolved
@@ -221,6 +223,7 @@ private:
IndexCache propertyIndexCache;
IndexCache methodIndexCache;
+ IndexCache signalHandlerIndexCache;
StringCache stringCache;
AllowedRevisionCache allowedRevisionCache;
v8::Persistent<v8::Function> constructor;
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index d90545308f..2bf1dd6981 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -1130,7 +1130,7 @@ void QDeclarativeVMEStack<T>::push(const T &o) {
Q_ASSERT(_index <= VLA::size());
if (_index == VLA::size())
- append(o);
+ this->append(o);
else
VLA::data()[_index] = o;
}
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 7ef28c0231..61e3aa3ab9 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -23,7 +23,6 @@ SOURCES += \
$$PWD/qdeclarativeinfo.cpp \
$$PWD/qdeclarativeerror.cpp \
$$PWD/qdeclarativescript.cpp \
- $$PWD/qdeclarativeenginedebug.cpp \
$$PWD/qdeclarativerewrite.cpp \
$$PWD/qdeclarativevaluetype.cpp \
$$PWD/qdeclarativefastproperties.cpp \
@@ -81,7 +80,6 @@ HEADERS += \
$$PWD/qdeclarativedata_p.h \
$$PWD/qdeclarativeerror.h \
$$PWD/qdeclarativescript_p.h \
- $$PWD/qdeclarativeenginedebug_p.h \
$$PWD/qdeclarativerewrite_p.h \
$$PWD/qdeclarativevaluetype_p.h \
$$PWD/qdeclarativefastproperties_p.h \
diff --git a/src/declarative/qml/v8/qscripttools_p.h b/src/declarative/qml/v8/qscripttools_p.h
index c8dace0b9f..a718691556 100644
--- a/src/declarative/qml/v8/qscripttools_p.h
+++ b/src/declarative/qml/v8/qscripttools_p.h
@@ -51,7 +51,7 @@ public:
template<class N, QIntrusiveListNode N::*member>
void QScriptIntrusiveList<N, member>::insert(N *n)
{
- Q_ASSERT_X(!contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already");
+ Q_ASSERT_X(!this->contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already");
Q_ASSERT_X(!(n->*member).isInList(), Q_FUNC_INFO, "Can't insert a value which is in another list");
QIntrusiveList<N, member>::insert(n);
}
@@ -59,7 +59,7 @@ void QScriptIntrusiveList<N, member>::insert(N *n)
template<class N, QIntrusiveListNode N::*member>
void QScriptIntrusiveList<N, member>::remove(N *n)
{
- Q_ASSERT_X(contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list");
+ Q_ASSERT_X(this->contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list");
QIntrusiveList<N, member>::remove(n);
}
diff --git a/src/declarative/qml/v8/qv8debug_p.h b/src/declarative/qml/v8/qv8debug_p.h
index e6bfdb7845..f5cbffb4fe 100644
--- a/src/declarative/qml/v8/qv8debug_p.h
+++ b/src/declarative/qml/v8/qv8debug_p.h
@@ -1 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 <private/v8-debug.h>
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
index 8eaf9024ea..6f584174c9 100644
--- a/src/declarative/qml/v8/qv8engine.cpp
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -43,6 +43,7 @@
#include "qv8contextwrapper_p.h"
#include "qv8valuetypewrapper_p.h"
+#include "qv8gccallback_p.h"
#include "qv8include_p.h"
#include "../../../3rdparty/javascriptcore/DateMath.h"
@@ -134,6 +135,7 @@ QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
v8::Context::Scope context_scope(m_context);
v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback);
+ QV8GCCallback::registerGcPrologueCallback();
m_stringWrapper.init();
m_contextWrapper.init(this);
@@ -208,7 +210,6 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
if (r) {
switch (r->resourceType()) {
case QV8ObjectResource::ContextType:
- case QV8ObjectResource::TypeType:
case QV8ObjectResource::XMLHttpRequestType:
case QV8ObjectResource::DOMNodeType:
case QV8ObjectResource::SQLDatabaseType:
@@ -216,6 +217,8 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
case QV8ObjectResource::Context2DType:
case QV8ObjectResource::ParticleDataType:
return QVariant();
+ case QV8ObjectResource::TypeType:
+ return m_typeWrapper.toVariant(r);
case QV8ObjectResource::QObjectType:
return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
case QV8ObjectResource::ListType:
@@ -2292,5 +2295,142 @@ void QV8Engine::emitSignalHandlerException()
emit q->signalHandlerException(scriptValueFromInternal(uncaughtException()));
}
+QThreadStorage<QV8GCCallback::ThreadData *> QV8GCCallback::threadData;
+void QV8GCCallback::initializeThreadData()
+{
+ QV8GCCallback::ThreadData *newThreadData = new QV8GCCallback::ThreadData;
+ threadData.setLocalData(newThreadData);
+}
+
+void QV8GCCallback::registerGcPrologueCallback()
+{
+ if (!threadData.hasLocalData())
+ initializeThreadData();
+
+ QV8GCCallback::ThreadData *td = threadData.localData();
+ if (!td->gcPrologueCallbackRegistered) {
+ td->gcPrologueCallbackRegistered = true;
+ v8::V8::AddGCPrologueCallback(QV8GCCallback::garbageCollectorPrologueCallback, v8::kGCTypeMarkSweepCompact);
+ }
+}
+
+QV8GCCallback::Node::Node(PrologueCallback callback)
+ : prologueCallback(callback)
+{
+}
+
+QV8GCCallback::Node::~Node()
+{
+ node.remove();
+}
+
+QV8GCCallback::Referencer::Referencer()
+{
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> context = v8::Context::New();
+ v8::Context::Scope contextScope(context);
+ strongReferencer = qPersistentNew(v8::Object::New());
+}
+
+void QV8GCCallback::Referencer::addRelationship(QObject *object, QObject *other)
+{
+ bool handleShouldBeStrong = false;
+ v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong);
+ v8::Persistent<v8::Value> handle = QDeclarativeData::get(other, true)->v8object;
+ if (handleShouldBeStrong) {
+ v8::V8::AddImplicitReferences(strongReferencer, &handle, 1);
+ } else if (!implicitOwner->IsEmpty()) {
+ v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1);
+ }
+}
+
+void QV8GCCallback::Referencer::addRelationship(QObject *object, v8::Persistent<v8::Value> handle)
+{
+ if (handle.IsEmpty())
+ return;
+
+ bool handleShouldBeStrong = false;
+ v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong);
+ if (handleShouldBeStrong) {
+ v8::V8::AddImplicitReferences(strongReferencer, &handle, 1);
+ } else if (!implicitOwner->IsEmpty()) {
+ v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1);
+ }
+}
+
+v8::Persistent<v8::Object> *QV8GCCallback::Referencer::findOwnerAndStrength(QObject *object, bool *shouldBeStrong)
+{
+ QObject *parent = object->parent();
+ if (!parent) {
+ // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value.
+ if (QDeclarativeEngine::objectOwnership(object) == QDeclarativeEngine::JavaScriptOwnership) {
+ *shouldBeStrong = false;
+ return &(QDeclarativeData::get(object)->v8object);
+ }
+
+ // no parent, and has CPP ownership - doesn't have an implicit parent.
+ *shouldBeStrong = true;
+ return 0;
+ }
+
+ // if it is owned by CPP, it's root parent may still be owned by JS.
+ // in that case, the owner of the persistent handle is the root parent's v8object.
+ while (parent->parent())
+ parent = parent->parent();
+
+ if (QDeclarativeEngine::objectOwnership(parent) == QDeclarativeEngine::JavaScriptOwnership) {
+ // root parent is owned by JS. It's v8object owns the persistent value in question.
+ *shouldBeStrong = false;
+ return &(QDeclarativeData::get(parent)->v8object);
+ } else {
+ // root parent has CPP ownership. The persistent value should not be made weak.
+ *shouldBeStrong = true;
+ return 0;
+ }
+}
+
+/*
+ Ensure that each persistent handle is strong if it has CPP ownership
+ and has no implicitly JS owned object owner in its parent chain, and
+ weak otherwise.
+
+ Any weak handle whose parent object is still alive will have an implicit
+ reference (between the parent and the handle) added, so that it will
+ not be collected.
+
+ Note that this callback is registered only for kGCTypeMarkSweepCompact
+ collection cycles, as it is during collection cycles of that type
+ in which weak persistent handle callbacks are called when required.
+ */
+void QV8GCCallback::garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags)
+{
+ if (!threadData.hasLocalData())
+ return;
+
+ QV8GCCallback::ThreadData *td = threadData.localData();
+ QV8GCCallback::Node *currNode = td->gcCallbackNodes.first();
+
+ while (currNode) {
+ // The client which adds itself to the list is responsible
+ // for maintaining the correct implicit references in the
+ // specified callback.
+ currNode->prologueCallback(&td->referencer, currNode);
+ currNode = td->gcCallbackNodes.next(currNode);
+ }
+}
+
+void QV8GCCallback::addGcCallbackNode(QV8GCCallback::Node *node)
+{
+ if (!threadData.hasLocalData())
+ initializeThreadData();
+
+ QV8GCCallback::ThreadData *td = threadData.localData();
+ td->gcCallbackNodes.insert(node);
+}
+
+QV8GCCallback::ThreadData::~ThreadData()
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
index bd5f360748..6f09e977d5 100644
--- a/src/declarative/qml/v8/qv8engine_p.h
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -135,7 +135,7 @@ public:
QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
- ListModelType, Context2DType, ParticleDataType };
+ ListModelType, Context2DType, ParticleDataType, SignalHandlerType };
virtual ResourceType resourceType() const = 0;
QV8Engine *engine;
@@ -470,7 +470,6 @@ private:
ValueIteratorList m_valueIterators;
Q_DISABLE_COPY(QV8Engine)
- friend class QV8DebugService;
};
// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated
diff --git a/src/declarative/qml/v8/qv8gccallback_p.h b/src/declarative/qml/v8/qv8gccallback_p.h
new file mode 100644
index 0000000000..095c0e5bac
--- /dev/null
+++ b/src/declarative/qml/v8/qv8gccallback_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QV8GCCALLBACK_P_H
+#define QV8GCCALLBACK_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qthreadstorage.h>
+#include <private/qv8_p.h>
+#include <private/qintrusivelist_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QV8GCCallback
+{
+private:
+ class ThreadData;
+public:
+ static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags);
+ static void registerGcPrologueCallback();
+
+ class Referencer {
+ public:
+ ~Referencer() {}
+ void addRelationship(QObject *object, v8::Persistent<v8::Value> handle);
+ void addRelationship(QObject *object, QObject *other);
+ private:
+ Referencer();
+ static v8::Persistent<v8::Object> *findOwnerAndStrength(QObject *qobjectOwner, bool *shouldBeStrong);
+ v8::Persistent<v8::Object> strongReferencer;
+ friend class QV8GCCallback::ThreadData;
+ };
+
+ class Node {
+ public:
+ typedef void (*PrologueCallback)(Referencer *r, Node *node);
+ Node(PrologueCallback callback);
+ ~Node();
+
+ QIntrusiveListNode node;
+ PrologueCallback prologueCallback;
+ };
+
+ static void addGcCallbackNode(Node *node);
+
+private:
+ class ThreadData {
+ public:
+ ThreadData() : gcPrologueCallbackRegistered(false) { }
+ ~ThreadData();
+ Referencer referencer;
+ bool gcPrologueCallbackRegistered;
+ QIntrusiveList<Node, &Node::node> gcCallbackNodes;
+ };
+
+ static void initializeThreadData();
+ static QThreadStorage<ThreadData *> threadData;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8GCCALLBACK_P_H
+
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
index 46494daf55..348b6c061d 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -109,6 +109,16 @@ public:
QV8QObjectWrapper *wrapper;
};
+class QV8SignalHandlerResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(SignalHandlerType)
+public:
+ QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index);
+
+ QDeclarativeGuard<QObject> object;
+ int index;
+};
+
namespace {
struct MetaCallArgument {
inline MetaCallArgument();
@@ -152,6 +162,11 @@ QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object)
{
}
+QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index)
+: QV8ObjectResource(engine), object(object), index(index)
+{
+}
+
static QAtomicInt objectIdCounter(1);
QV8QObjectWrapper::QV8QObjectWrapper()
@@ -177,6 +192,7 @@ void QV8QObjectWrapper::destroy()
qPersistentDispose(m_hiddenObject);
qPersistentDispose(m_destroySymbol);
qPersistentDispose(m_toStringSymbol);
+ qPersistentDispose(m_signalHandlerConstructor);
qPersistentDispose(m_methodConstructor);
qPersistentDispose(m_constructor);
}
@@ -278,10 +294,21 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
m_methodConstructor = qPersistentNew<v8::Function>(createFn);
}
+ v8::Local<v8::Function> connect = V8FUNCTION(Connect, engine);
+ v8::Local<v8::Function> disconnect = V8FUNCTION(Disconnect, engine);
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum);
+ ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
+ m_signalHandlerConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
+ }
+
{
v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
- prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine), v8::DontEnum);
- prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine), v8::DontEnum);
+ prototype->Set(v8::String::New("connect"), connect, v8::DontEnum);
+ prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
}
}
@@ -461,6 +488,11 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
} else if (result->isV8Function()) {
return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
+ } else if (result->isSignalHandler()) {
+ v8::Local<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance();
+ QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex);
+ handler->SetExternalResource(r);
+ return handler;
} else {
return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
}
@@ -998,6 +1030,17 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
}
}
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
+{
+ if (object->IsFunction())
+ return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object));
+
+ if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object))
+ return qMakePair(resource->object.data(), resource->index);
+
+ return qMakePair((QObject *)0, -1);
+}
+
QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
{
v8::ScriptOrigin origin = function->GetScriptOrigin();
@@ -1167,10 +1210,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args)
QV8Engine *engine = V8ENGINE();
- if (!args.This()->IsFunction())
- V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
-
- QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
@@ -1229,10 +1269,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
QV8Engine *engine = V8ENGINE();
- if (!args.This()->IsFunction())
- V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
-
- QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper_p.h b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
index d0a489bed8..be118a9c34 100644
--- a/src/declarative/qml/v8/qv8qobjectwrapper_p.h
+++ b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
@@ -111,11 +111,13 @@ private:
static v8::Handle<v8::Value> Disconnect(const v8::Arguments &args);
static v8::Handle<v8::Value> Invoke(const v8::Arguments &args);
static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, v8::Handle<v8::Function>);
+ static QPair<QObject *, int> ExtractQtSignal(QV8Engine *, v8::Handle<v8::Object>);
QV8Engine *m_engine;
quint32 m_id;
v8::Persistent<v8::Function> m_constructor;
v8::Persistent<v8::Function> m_methodConstructor;
+ v8::Persistent<v8::Function> m_signalHandlerConstructor;
v8::Persistent<v8::String> m_toStringSymbol;
v8::Persistent<v8::String> m_destroySymbol;
QHashedV8String m_toStringString;
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
index f46aaab320..c89d5ab8ae 100644
--- a/src/declarative/qml/v8/qv8typewrapper.cpp
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -128,6 +128,34 @@ v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeName
return rv;
}
+QVariant QV8TypeWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::TypeType);
+ QV8TypeResource *resource = static_cast<QV8TypeResource *>(r);
+ QV8Engine *v8engine = resource->engine;
+
+ if (resource->typeNamespace) {
+ if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) {
+ if (moduleApi->scriptCallback) {
+ moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
+ moduleApi->scriptCallback = 0;
+ moduleApi->qobjectCallback = 0;
+ } else if (moduleApi->qobjectCallback) {
+ moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine());
+ moduleApi->scriptCallback = 0;
+ moduleApi->qobjectCallback = 0;
+ }
+
+ if (moduleApi->qobjectApi) {
+ return QVariant::fromValue<QObject*>(moduleApi->qobjectApi);
+ }
+ }
+ }
+
+ // only QObject Module API can be converted to a variant.
+ return QVariant();
+}
+
v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
{
diff --git a/src/declarative/qml/v8/qv8typewrapper_p.h b/src/declarative/qml/v8/qv8typewrapper_p.h
index 2e79946a6e..f9309f8e28 100644
--- a/src/declarative/qml/v8/qv8typewrapper_p.h
+++ b/src/declarative/qml/v8/qv8typewrapper_p.h
@@ -75,6 +75,7 @@ public:
v8::Local<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, const void *,
TypeNameMode = IncludeEnums);
+ QVariant toVariant(QV8ObjectResource *);
private:
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
index 175efd6b6c..4b642179d3 100644
--- a/src/declarative/qml/v8/v8.pri
+++ b/src/declarative/qml/v8/v8.pri
@@ -8,6 +8,7 @@ HEADERS += \
$$PWD/qv8debug_p.h \
$$PWD/qv8stringwrapper_p.h \
$$PWD/qv8engine_p.h \
+ $$PWD/qv8gccallback_p.h \
$$PWD/qv8contextwrapper_p.h \
$$PWD/qv8qobjectwrapper_p.h \
$$PWD/qv8typewrapper_p.h \
diff --git a/src/declarative/util/qdeclarativepath.cpp b/src/declarative/util/qdeclarativepath.cpp
index 34752b5242..57387f5ddd 100644
--- a/src/declarative/util/qdeclarativepath.cpp
+++ b/src/declarative/util/qdeclarativepath.cpp
@@ -41,6 +41,7 @@
#include "private/qdeclarativepath_p.h"
#include "private/qdeclarativepath_p_p.h"
+#include "private/qdeclarativesvgparser_p.h"
#include <QSet>
#include <QTime>
@@ -97,35 +98,47 @@ QDeclarativePath::~QDeclarativePath()
qreal QDeclarativePath::startX() const
{
Q_D(const QDeclarativePath);
- return d->startX;
+ return d->startX.isNull ? 0 : d->startX.value;
}
void QDeclarativePath::setStartX(qreal x)
{
Q_D(QDeclarativePath);
- if (qFuzzyCompare(x, d->startX))
+ if (d->startX.isValid() && qFuzzyCompare(x, d->startX))
return;
d->startX = x;
emit startXChanged();
processPath();
}
+bool QDeclarativePath::hasStartX() const
+{
+ Q_D(const QDeclarativePath);
+ return d->startX.isValid();
+}
+
qreal QDeclarativePath::startY() const
{
Q_D(const QDeclarativePath);
- return d->startY;
+ return d->startY.isNull ? 0 : d->startY.value;
}
void QDeclarativePath::setStartY(qreal y)
{
Q_D(QDeclarativePath);
- if (qFuzzyCompare(y, d->startY))
+ if (d->startY.isValid() && qFuzzyCompare(y, d->startY))
return;
d->startY = y;
emit startYChanged();
processPath();
}
+bool QDeclarativePath::hasStartY() const
+{
+ Q_D(const QDeclarativePath);
+ return d->startY.isValid();
+}
+
/*!
\qmlproperty bool QtQuick2::Path::closed
This property holds whether the start and end of the path are identical.
@@ -163,6 +176,11 @@ QDeclarativeListProperty<QDeclarativePathElement> QDeclarativePath::pathElements
void QDeclarativePath::interpolate(int idx, const QString &name, qreal value)
{
Q_D(QDeclarativePath);
+ interpolate(d->_attributePoints, idx, name, value);
+}
+
+void QDeclarativePath::interpolate(QList<AttributePoint> &attributePoints, int idx, const QString &name, qreal value)
+{
if (!idx)
return;
@@ -170,7 +188,7 @@ void QDeclarativePath::interpolate(int idx, const QString &name, qreal value)
qreal lastPercent = 0;
int search = idx - 1;
while(search >= 0) {
- const AttributePoint &point = d->_attributePoints.at(search);
+ const AttributePoint &point = attributePoints.at(search);
if (point.values.contains(name)) {
lastValue = point.values.value(name);
lastPercent = point.origpercent;
@@ -181,10 +199,10 @@ void QDeclarativePath::interpolate(int idx, const QString &name, qreal value)
++search;
- const AttributePoint &curPoint = d->_attributePoints.at(idx);
+ const AttributePoint &curPoint = attributePoints.at(idx);
for (int ii = search; ii < idx; ++ii) {
- AttributePoint &point = d->_attributePoints[ii];
+ AttributePoint &point = attributePoints[ii];
qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
point.values.insert(name, val);
@@ -208,6 +226,22 @@ void QDeclarativePath::endpoint(const QString &name)
}
}
+void QDeclarativePath::endpoint(QList<AttributePoint> &attributePoints, const QString &name)
+{
+ const AttributePoint &first = attributePoints.first();
+ qreal val = first.values.value(name);
+ for (int ii = attributePoints.count() - 1; ii >= 0; ii--) {
+ const AttributePoint &point = attributePoints.at(ii);
+ if (point.values.contains(name)) {
+ for (int jj = ii + 1; jj < attributePoints.count(); ++jj) {
+ AttributePoint &setPoint = attributePoints[jj];
+ setPoint.values.insert(name, val);
+ }
+ return;
+ }
+ }
+}
+
static QString percentString(QStringLiteral("_qfx_percent"));
void QDeclarativePath::processPath()
@@ -218,42 +252,64 @@ void QDeclarativePath::processPath()
return;
d->_pointCache.clear();
- d->_attributePoints.clear();
- d->_path = QPainterPath();
+ d->prevBez.isValid = false;
+
+ d->_path = createPath(QPointF(), QPointF(), d->_attributes, d->pathLength, d->_attributePoints, &d->closed);
+
+ emit changed();
+}
+
+QPainterPath QDeclarativePath::createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed)
+{
+ Q_D(QDeclarativePath);
+
+ pathLength = 0;
+ attributePoints.clear();
+
+ if (!d->componentComplete)
+ return QPainterPath();
+
+ QPainterPath path;
AttributePoint first;
- for (int ii = 0; ii < d->_attributes.count(); ++ii)
- first.values[d->_attributes.at(ii)] = 0;
- d->_attributePoints << first;
+ for (int ii = 0; ii < attributes.count(); ++ii)
+ first.values[attributes.at(ii)] = 0;
+ attributePoints << first;
- d->_path.moveTo(d->startX, d->startY);
+ qreal startX = d->startX.isValid() ? d->startX.value : startPoint.x();
+ qreal startY = d->startY.isValid() ? d->startY.value : startPoint.y();
+ path.moveTo(startX, startY);
- QDeclarativeCurve *lastCurve = 0;
bool usesPercent = false;
+ int index = 0;
foreach (QDeclarativePathElement *pathElement, d->_pathElements) {
if (QDeclarativeCurve *curve = qobject_cast<QDeclarativeCurve *>(pathElement)) {
- curve->addToPath(d->_path);
+ QDeclarativePathData data;
+ data.index = index;
+ data.endPoint = endPoint;
+ data.curves = d->_pathCurves;
+ curve->addToPath(path, data);
AttributePoint p;
- p.origpercent = d->_path.length();
- d->_attributePoints << p;
- lastCurve = curve;
+ p.origpercent = path.length();
+ attributePoints << p;
+ ++index;
} else if (QDeclarativePathAttribute *attribute = qobject_cast<QDeclarativePathAttribute *>(pathElement)) {
- AttributePoint &point = d->_attributePoints.last();
+ AttributePoint &point = attributePoints.last();
point.values[attribute->name()] = attribute->value();
- interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
+ interpolate(attributePoints, attributePoints.count() - 1, attribute->name(), attribute->value());
} else if (QDeclarativePathPercent *percent = qobject_cast<QDeclarativePathPercent *>(pathElement)) {
- AttributePoint &point = d->_attributePoints.last();
+ AttributePoint &point = attributePoints.last();
point.values[percentString] = percent->value();
- interpolate(d->_attributePoints.count() - 1, percentString, percent->value());
+ interpolate(attributePoints, attributePoints.count() - 1, percentString, percent->value());
usesPercent = true;
}
}
// Fixup end points
- const AttributePoint &last = d->_attributePoints.last();
- for (int ii = 0; ii < d->_attributes.count(); ++ii) {
- if (!last.values.contains(d->_attributes.at(ii)))
- endpoint(d->_attributes.at(ii));
+ const AttributePoint &last = attributePoints.last();
+ for (int ii = 0; ii < attributes.count(); ++ii) {
+ if (!last.values.contains(attributes.at(ii)))
+ endpoint(attributePoints, attributes.at(ii));
}
if (usesPercent && !last.values.contains(percentString)) {
d->_attributePoints.last().values[percentString] = 1;
@@ -262,30 +318,34 @@ void QDeclarativePath::processPath()
// Adjust percent
- qreal length = d->_path.length();
+ qreal length = path.length();
qreal prevpercent = 0;
qreal prevorigpercent = 0;
- for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
- const AttributePoint &point = d->_attributePoints.at(ii);
+ for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ const AttributePoint &point = attributePoints.at(ii);
if (point.values.contains(percentString)) { //special string for QDeclarativePathPercent
if ( ii > 0) {
- qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
+ qreal scale = (attributePoints[ii].origpercent/length - prevorigpercent) /
(point.values.value(percentString)-prevpercent);
- d->_attributePoints[ii].scale = scale;
+ attributePoints[ii].scale = scale;
}
- d->_attributePoints[ii].origpercent /= length;
- d->_attributePoints[ii].percent = point.values.value(percentString);
- prevorigpercent = d->_attributePoints[ii].origpercent;
- prevpercent = d->_attributePoints[ii].percent;
+ attributePoints[ii].origpercent /= length;
+ attributePoints[ii].percent = point.values.value(percentString);
+ prevorigpercent = attributePoints[ii].origpercent;
+ prevpercent = attributePoints[ii].percent;
} else {
- d->_attributePoints[ii].origpercent /= length;
- d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
+ attributePoints[ii].origpercent /= length;
+ attributePoints[ii].percent = attributePoints[ii].origpercent;
}
}
- d->closed = lastCurve && d->startX == lastCurve->x() && d->startY == lastCurve->y();
+ if (closed) {
+ QPointF end = path.currentPosition();
+ *closed = length > 0 && startX == end.x() && startY == end.y();
+ }
+ pathLength = length;
- emit changed();
+ return path;
}
void QDeclarativePath::classBegin()
@@ -302,8 +362,11 @@ void QDeclarativePath::componentComplete()
// First gather up all the attributes
foreach (QDeclarativePathElement *pathElement, d->_pathElements) {
- if (QDeclarativePathAttribute *attribute =
- qobject_cast<QDeclarativePathAttribute *>(pathElement))
+ if (QDeclarativeCurve *curve =
+ qobject_cast<QDeclarativeCurve *>(pathElement))
+ d->_pathCurves.append(curve);
+ else if (QDeclarativePathAttribute *attribute =
+ qobject_cast<QDeclarativePathAttribute *>(pathElement))
attrs.insert(attribute->name());
}
d->_attributes = attrs.toList();
@@ -337,10 +400,10 @@ QStringList QDeclarativePath::attributes() const
return d->_attributes;
}
-static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
+static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength, bool reverse = false)
{
- const int lastElement = path.elementCount() - 1;
- for (int i=*from; i <= lastElement; ++i) {
+ const int lastElement = reverse ? 0 : path.elementCount() - 1;
+ for (int i=*from; reverse ? i >= lastElement : i <= lastElement; reverse ? --i : ++i) {
const QPainterPath::Element &e = path.elementAt(i);
switch (e.type) {
@@ -352,7 +415,7 @@ static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bez
*bezLength = line.length();
QPointF a = path.elementAt(i-1);
QPointF delta = e - a;
- *from = i+1;
+ *from = reverse ? i-1 : i+1;
return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
}
case QPainterPath::CurveToElement:
@@ -362,7 +425,7 @@ static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bez
path.elementAt(i+1),
path.elementAt(i+2));
*bezLength = b.length();
- *from = i+3;
+ *from = reverse ? i-1 : i+3;
return b;
}
default:
@@ -374,10 +437,16 @@ static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bez
return QBezier();
}
+//derivative of the equation
+static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
+{
+ return 3*t*t*(d - 3*c + 3*b - a) + 6*t*(c - 2*b + a) + 3*(b - a);
+}
+
void QDeclarativePath::createPointCache() const
{
Q_D(const QDeclarativePath);
- qreal pathLength = d->_path.length();
+ qreal pathLength = d->pathLength;
if (pathLength <= 0 || qIsNaN(pathLength))
return;
// more points means less jitter between items as they move along the
@@ -426,6 +495,140 @@ void QDeclarativePath::createPointCache() const
}
}
+QPointF QDeclarativePath::sequentialPointAt(qreal p, qreal *angle) const
+{
+ Q_D(const QDeclarativePath);
+ return sequentialPointAt(d->_path, d->pathLength, d->_attributePoints, d->prevBez, p, angle);
+}
+
+QPointF QDeclarativePath::sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle)
+{
+ if (!prevBez.isValid)
+ return p > .5 ? backwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle) :
+ forwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle);
+
+ return p < prevBez.p ? backwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle) :
+ forwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle);
+}
+
+QPointF QDeclarativePath::forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle)
+{
+ if (pathLength <= 0 || qIsNaN(pathLength))
+ return path.pointAtPercent(0); //expensive?
+
+ const int lastElement = path.elementCount() - 1;
+ bool haveCachedBez = prevBez.isValid;
+ int currElement = haveCachedBez ? prevBez.element : 0;
+ qreal bezLength = haveCachedBez ? prevBez.bezLength : 0;
+ QBezier currBez = haveCachedBez ? prevBez.bezier : nextBezier(path, &currElement, &bezLength);
+ qreal currLength = haveCachedBez ? prevBez.currLength : bezLength;
+ qreal epc = currLength / pathLength;
+
+ //find which set we are in
+ qreal prevPercent = 0;
+ qreal prevOrigPercent = 0;
+ for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ qreal percent = p;
+ const AttributePoint &point = attributePoints.at(ii);
+ if (percent < point.percent || ii == attributePoints.count() - 1) {
+ qreal elementPercent = (percent - prevPercent);
+
+ qreal spc = prevOrigPercent + elementPercent * point.scale;
+
+ while (spc > epc) {
+ if (currElement > lastElement)
+ break;
+ currBez = nextBezier(path, &currElement, &bezLength);
+ /*if (bezLength == 0.0) {
+ currLength = pathLength;
+ epc = 1.0;
+ break;
+ }*/
+ currLength += bezLength;
+ epc = currLength / pathLength;
+ }
+ prevBez.element = currElement;
+ prevBez.bezLength = bezLength;
+ prevBez.currLength = currLength;
+ prevBez.bezier = currBez;
+ prevBez.p = p;
+ prevBez.isValid = true;
+
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+
+ if (angle) {
+ qreal m1 = slopeAt(realT, currBez.x1, currBez.x2, currBez.x3, currBez.x4);
+ qreal m2 = slopeAt(realT, currBez.y1, currBez.y2, currBez.y3, currBez.y4);
+ *angle = QLineF(0, 0, m1, m2).angle();
+ }
+
+ return currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ }
+ prevOrigPercent = point.origpercent;
+ prevPercent = point.percent;
+ }
+
+ return QPointF(0,0);
+}
+
+//ideally this should be merged with forwardsPointAt
+QPointF QDeclarativePath::backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle)
+{
+ if (pathLength <= 0 || qIsNaN(pathLength))
+ return path.pointAtPercent(0);
+
+ const int firstElement = 0;
+ bool haveCachedBez = prevBez.isValid;
+ int currElement = haveCachedBez ? prevBez.element : path.elementCount() - 1;
+ qreal bezLength = haveCachedBez ? prevBez.bezLength : 0;
+ QBezier currBez = haveCachedBez ? prevBez.bezier : nextBezier(path, &currElement, &bezLength, true /*reverse*/);
+ qreal currLength = haveCachedBez ? prevBez.currLength : pathLength;
+ qreal prevLength = currLength - bezLength;
+ qreal epc = prevLength / pathLength;
+
+ for (int ii = attributePoints.count() - 1; ii > 0; --ii) {
+ qreal percent = p;
+ const AttributePoint &point = attributePoints.at(ii);
+ const AttributePoint &prevPoint = attributePoints.at(ii-1);
+ if (percent > prevPoint.percent || ii == 1) {
+ qreal elementPercent = (percent - prevPoint.percent);
+
+ qreal spc = prevPoint.origpercent + elementPercent * point.scale;
+
+ while (spc < epc) {
+ if (currElement < firstElement)
+ break;
+ currBez = nextBezier(path, &currElement, &bezLength, true /*reverse*/);
+ /*if (bezLength == 0.0) {
+ currLength = 0;
+ epc = 0.0;
+ break;
+ }*/
+ currLength = prevLength;
+ epc = (currLength - bezLength) / pathLength;
+ }
+ prevBez.element = currElement;
+ prevBez.bezLength = bezLength;
+ prevBez.currLength = currLength;
+ prevBez.bezier = currBez;
+ prevBez.p = p;
+ prevBez.isValid = true;
+
+ qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
+
+ if (angle) {
+ qreal m1 = slopeAt(realT, currBez.x1, currBez.x2, currBez.x3, currBez.x4);
+ qreal m2 = slopeAt(realT, currBez.y1, currBez.y2, currBez.y3, currBez.y4);
+ *angle = QLineF(0, 0, m1, m2).angle();
+ }
+
+ return currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
+ }
+ }
+
+ return QPointF(0,0);
+}
+
QPointF QDeclarativePath::pointAt(qreal p) const
{
Q_D(const QDeclarativePath);
@@ -472,32 +675,80 @@ qreal QDeclarativePath::attributeAt(const QString &name, qreal percent) const
qreal QDeclarativeCurve::x() const
{
- return _x;
+ return _x.isNull ? 0 : _x.value;
}
void QDeclarativeCurve::setX(qreal x)
{
- if (_x != x) {
+ if (_x.isNull || _x != x) {
_x = x;
emit xChanged();
emit changed();
}
}
+bool QDeclarativeCurve::hasX()
+{
+ return _x.isValid();
+}
+
qreal QDeclarativeCurve::y() const
{
- return _y;
+ return _y.isNull ? 0 : _y.value;
}
void QDeclarativeCurve::setY(qreal y)
{
- if (_y != y) {
+ if (_y.isNull || _y != y) {
_y = y;
emit yChanged();
emit changed();
}
}
+bool QDeclarativeCurve::hasY()
+{
+ return _y.isValid();
+}
+
+qreal QDeclarativeCurve::relativeX() const
+{
+ return _relativeX;
+}
+
+void QDeclarativeCurve::setRelativeX(qreal x)
+{
+ if (_relativeX.isNull || _relativeX != x) {
+ _relativeX = x;
+ emit relativeXChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativeCurve::hasRelativeX()
+{
+ return _relativeX.isValid();
+}
+
+qreal QDeclarativeCurve::relativeY() const
+{
+ return _relativeY;
+}
+
+void QDeclarativeCurve::setRelativeY(qreal y)
+{
+ if (_relativeY.isNull || _relativeY != y) {
+ _relativeY = y;
+ emit relativeYChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativeCurve::hasRelativeY()
+{
+ return _relativeY.isValid();
+}
+
/****************************************************************************/
/*!
@@ -642,9 +893,17 @@ void QDeclarativePathAttribute::setValue(qreal value)
Defines the end point of the line.
*/
-void QDeclarativePathLine::addToPath(QPainterPath &path)
+inline QPointF positionForCurve(const QDeclarativePathData &data, const QPointF &prevPoint)
{
- path.lineTo(x(), y());
+ QDeclarativeCurve *curve = data.curves.at(data.index);
+ bool isEnd = data.index == data.curves.size() - 1;
+ return QPointF(curve->hasRelativeX() ? prevPoint.x() + curve->relativeX() : !isEnd || curve->hasX() ? curve->x() : data.endPoint.x(),
+ curve->hasRelativeY() ? prevPoint.y() + curve->relativeY() : !isEnd || curve->hasY() ? curve->y() : data.endPoint.y());
+}
+
+void QDeclarativePathLine::addToPath(QPainterPath &path, const QDeclarativePathData &data)
+{
+ path.lineTo(positionForCurve(data, path.currentPosition()));
}
/****************************************************************************/
@@ -720,9 +979,50 @@ void QDeclarativePathQuad::setControlY(qreal y)
}
}
-void QDeclarativePathQuad::addToPath(QPainterPath &path)
+qreal QDeclarativePathQuad::relativeControlX() const
+{
+ return _relativeControlX;
+}
+
+void QDeclarativePathQuad::setRelativeControlX(qreal x)
+{
+ if (_relativeControlX.isNull || _relativeControlX != x) {
+ _relativeControlX = x;
+ emit relativeControlXChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathQuad::hasRelativeControlX()
+{
+ return _relativeControlX.isValid();
+}
+
+qreal QDeclarativePathQuad::relativeControlY() const
+{
+ return _relativeControlY;
+}
+
+void QDeclarativePathQuad::setRelativeControlY(qreal y)
+{
+ if (_relativeControlY.isNull || _relativeControlY != y) {
+ _relativeControlY = y;
+ emit relativeControlYChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathQuad::hasRelativeControlY()
{
- path.quadTo(controlX(), controlY(), x(), y());
+ return _relativeControlY.isValid();
+}
+
+void QDeclarativePathQuad::addToPath(QPainterPath &path, const QDeclarativePathData &data)
+{
+ const QPointF &prevPoint = path.currentPosition();
+ QPointF controlPoint(hasRelativeControlX() ? prevPoint.x() + relativeControlX() : controlX(),
+ hasRelativeControlY() ? prevPoint.y() + relativeControlY() : controlY());
+ path.quadTo(controlPoint, positionForCurve(data, path.currentPosition()));
}
/****************************************************************************/
@@ -828,9 +1128,256 @@ void QDeclarativePathCubic::setControl2Y(qreal y)
}
}
-void QDeclarativePathCubic::addToPath(QPainterPath &path)
+qreal QDeclarativePathCubic::relativeControl1X() const
+{
+ return _relativeControl1X;
+}
+
+void QDeclarativePathCubic::setRelativeControl1X(qreal x)
+{
+ if (_relativeControl1X.isNull || _relativeControl1X != x) {
+ _relativeControl1X = x;
+ emit relativeControl1XChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathCubic::hasRelativeControl1X()
+{
+ return _relativeControl1X.isValid();
+}
+
+qreal QDeclarativePathCubic::relativeControl1Y() const
+{
+ return _relativeControl1Y;
+}
+
+void QDeclarativePathCubic::setRelativeControl1Y(qreal y)
+{
+ if (_relativeControl1Y.isNull || _relativeControl1Y != y) {
+ _relativeControl1Y = y;
+ emit relativeControl1YChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathCubic::hasRelativeControl1Y()
+{
+ return _relativeControl1Y.isValid();
+}
+
+qreal QDeclarativePathCubic::relativeControl2X() const
+{
+ return _relativeControl2X;
+}
+
+void QDeclarativePathCubic::setRelativeControl2X(qreal x)
+{
+ if (_relativeControl2X.isNull || _relativeControl2X != x) {
+ _relativeControl2X = x;
+ emit relativeControl2XChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathCubic::hasRelativeControl2X()
+{
+ return _relativeControl2X.isValid();
+}
+
+qreal QDeclarativePathCubic::relativeControl2Y() const
+{
+ return _relativeControl2Y;
+}
+
+void QDeclarativePathCubic::setRelativeControl2Y(qreal y)
+{
+ if (_relativeControl2Y.isNull || _relativeControl2Y != y) {
+ _relativeControl2Y = y;
+ emit relativeControl2YChanged();
+ emit changed();
+ }
+}
+
+bool QDeclarativePathCubic::hasRelativeControl2Y()
+{
+ return _relativeControl2Y.isValid();
+}
+
+void QDeclarativePathCubic::addToPath(QPainterPath &path, const QDeclarativePathData &data)
+{
+ const QPointF &prevPoint = path.currentPosition();
+ QPointF controlPoint1(hasRelativeControl1X() ? prevPoint.x() + relativeControl1X() : control1X(),
+ hasRelativeControl1Y() ? prevPoint.y() + relativeControl1Y() : control1Y());
+ QPointF controlPoint2(hasRelativeControl2X() ? prevPoint.x() + relativeControl2X() : control2X(),
+ hasRelativeControl2Y() ? prevPoint.y() + relativeControl2Y() : control2Y());
+ path.cubicTo(controlPoint1, controlPoint2, positionForCurve(data, path.currentPosition()));
+}
+
+/****************************************************************************/
+
+inline QPointF previousPathPosition(const QPainterPath &path)
+{
+ int count = path.elementCount();
+ if (count < 1)
+ return QPointF();
+
+ int index = path.elementAt(count-1).type == QPainterPath::CurveToDataElement ? count - 4 : count - 2;
+ return index > -1 ? QPointF(path.elementAt(index)) : path.pointAtPercent(0);
+}
+
+void QDeclarativePathCatmullRomCurve::addToPath(QPainterPath &path, const QDeclarativePathData &data)
+{
+ //here we convert catmull-rom spline to bezier for use in QPainterPath.
+ //basic conversion algorithm:
+ // catmull-rom points * inverse bezier matrix * catmull-rom matrix = bezier points
+ //each point in the catmull-rom spline produces a bezier endpoint + 2 control points
+ //calculations for each point use a moving window of 4 points
+ // (previous 2 points + current point + next point)
+ QPointF prevFar, prev, point, next;
+
+ //get previous points
+ int index = data.index - 1;
+ QDeclarativeCurve *curve = index == -1 ? 0 : data.curves.at(index);
+ if (qobject_cast<QDeclarativePathCatmullRomCurve*>(curve)) {
+ prev = path.currentPosition();
+ prevFar = previousPathPosition(path);
+ } else
+ prevFar = prev = path.currentPosition();
+
+ //get current point
+ point = positionForCurve(data, path.currentPosition());
+
+ //get next point
+ index = data.index + 1;
+ if (index < data.curves.count() && qobject_cast<QDeclarativePathCatmullRomCurve*>(data.curves.at(index))) {
+ QDeclarativePathData nextData;
+ nextData.index = index;
+ nextData.endPoint = data.endPoint;
+ nextData.curves = data.curves;
+ next = positionForCurve(nextData, point);
+ } else
+ next = point;
+
+ /*
+ full conversion matrix (inverse bezier * catmull-rom):
+ 0.000, 1.000, 0.000, 0.000,
+ -0.167, 1.000, 0.167, 0.000,
+ 0.000, 0.167, 1.000, -0.167,
+ 0.000, 0.000, 1.000, 0.000
+
+ conversion doesn't require full matrix multiplication,
+ so below we simplify
+ */
+ QPointF control1(prevFar.x() * qreal(-0.167) +
+ prev.x() +
+ point.x() * qreal(0.167),
+ prevFar.y() * qreal(-0.167) +
+ prev.y() +
+ point.y() * qreal(0.167));
+
+ QPointF control2(prev.x() * qreal(0.167) +
+ point.x() +
+ next.x() * qreal(-0.167),
+ prev.y() * qreal(0.167) +
+ point.y() +
+ next.y() * qreal(-0.167));
+
+ path.cubicTo(control1, control2, point);
+}
+
+/****************************************************************************/
+
+qreal QDeclarativePathArc::radiusX() const
+{
+ return _radiusX;
+}
+
+void QDeclarativePathArc::setRadiusX(qreal radius)
+{
+ if (_radiusX == radius)
+ return;
+
+ _radiusX = radius;
+ emit radiusXChanged();
+}
+
+qreal QDeclarativePathArc::radiusY() const
+{
+ return _radiusY;
+}
+
+void QDeclarativePathArc::setRadiusY(qreal radius)
+{
+ if (_radiusY == radius)
+ return;
+
+ _radiusY = radius;
+ emit radiusYChanged();
+}
+
+bool QDeclarativePathArc::useLargeArc() const
+{
+ return _useLargeArc;
+}
+
+void QDeclarativePathArc::setUseLargeArc(bool largeArc)
+{
+ if (_useLargeArc == largeArc)
+ return;
+
+ _useLargeArc = largeArc;
+ emit useLargeArcChanged();
+}
+
+QDeclarativePathArc::ArcDirection QDeclarativePathArc::direction() const
+{
+ return _direction;
+}
+
+void QDeclarativePathArc::setDirection(ArcDirection direction)
+{
+ if (_direction == direction)
+ return;
+
+ _direction = direction;
+ emit directionChanged();
+}
+
+void QDeclarativePathArc::addToPath(QPainterPath &path, const QDeclarativePathData &data)
+{
+ const QPointF &startPoint = path.currentPosition();
+ const QPointF &endPoint = positionForCurve(data, startPoint);
+ QDeclarativeSvgParser::pathArc(path,
+ _radiusX,
+ _radiusY,
+ 0, //xAxisRotation
+ _useLargeArc,
+ _direction == Clockwise ? 1 : 0,
+ endPoint.x(),
+ endPoint.y(),
+ startPoint.x(), startPoint.y());
+}
+
+/****************************************************************************/
+
+QString QDeclarativePathSvg::path() const
+{
+ return _path;
+}
+
+void QDeclarativePathSvg::setPath(const QString &path)
+{
+ if (_path == path)
+ return;
+
+ _path = path;
+ emit pathChanged();
+}
+
+void QDeclarativePathSvg::addToPath(QPainterPath &path, const QDeclarativePathData &)
{
- path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
+ QDeclarativeSvgParser::parsePathDataFast(_path, path);
}
/****************************************************************************/
diff --git a/src/declarative/util/qdeclarativepath_p.h b/src/declarative/util/qdeclarativepath_p.h
index c8420eb996..4ce1bcf827 100644
--- a/src/declarative/util/qdeclarativepath_p.h
+++ b/src/declarative/util/qdeclarativepath_p.h
@@ -44,6 +44,9 @@
#include <qdeclarative.h>
+#include "private/qdeclarativenullablevalue_p_p.h"
+#include <private/qbezier_p.h>
+
#include <QtCore/QObject>
#include <QtGui/QPainterPath>
@@ -52,6 +55,15 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
+
+class QDeclarativeCurve;
+struct QDeclarativePathData
+{
+ int index;
+ QPointF endPoint;
+ QList<QDeclarativeCurve*> curves;
+};
+
class Q_AUTOTEST_EXPORT QDeclarativePathElement : public QObject
{
Q_OBJECT
@@ -92,24 +104,40 @@ class Q_AUTOTEST_EXPORT QDeclarativeCurve : public QDeclarativePathElement
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal relativeX READ relativeX WRITE setRelativeX NOTIFY relativeXChanged)
+ Q_PROPERTY(qreal relativeY READ relativeY WRITE setRelativeY NOTIFY relativeYChanged)
public:
- QDeclarativeCurve(QObject *parent=0) : QDeclarativePathElement(parent), _x(0), _y(0) {}
+ QDeclarativeCurve(QObject *parent=0) : QDeclarativePathElement(parent) {}
qreal x() const;
void setX(qreal x);
+ bool hasX();
qreal y() const;
void setY(qreal y);
+ bool hasY();
+
+ qreal relativeX() const;
+ void setRelativeX(qreal x);
+ bool hasRelativeX();
+
+ qreal relativeY() const;
+ void setRelativeY(qreal y);
+ bool hasRelativeY();
- virtual void addToPath(QPainterPath &) {}
+ virtual void addToPath(QPainterPath &, const QDeclarativePathData &) {}
Q_SIGNALS:
void xChanged();
void yChanged();
+ void relativeXChanged();
+ void relativeYChanged();
private:
- qreal _x;
- qreal _y;
+ QDeclarativeNullableValue<qreal> _x;
+ QDeclarativeNullableValue<qreal> _y;
+ QDeclarativeNullableValue<qreal> _relativeX;
+ QDeclarativeNullableValue<qreal> _relativeY;
};
class Q_AUTOTEST_EXPORT QDeclarativePathLine : public QDeclarativeCurve
@@ -118,7 +146,7 @@ class Q_AUTOTEST_EXPORT QDeclarativePathLine : public QDeclarativeCurve
public:
QDeclarativePathLine(QObject *parent=0) : QDeclarativeCurve(parent) {}
- void addToPath(QPainterPath &path);
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
};
class Q_AUTOTEST_EXPORT QDeclarativePathQuad : public QDeclarativeCurve
@@ -127,6 +155,8 @@ class Q_AUTOTEST_EXPORT QDeclarativePathQuad : public QDeclarativeCurve
Q_PROPERTY(qreal controlX READ controlX WRITE setControlX NOTIFY controlXChanged)
Q_PROPERTY(qreal controlY READ controlY WRITE setControlY NOTIFY controlYChanged)
+ Q_PROPERTY(qreal relativeControlX READ relativeControlX WRITE setRelativeControlX NOTIFY relativeControlXChanged)
+ Q_PROPERTY(qreal relativeControlY READ relativeControlY WRITE setRelativeControlY NOTIFY relativeControlYChanged)
public:
QDeclarativePathQuad(QObject *parent=0) : QDeclarativeCurve(parent), _controlX(0), _controlY(0) {}
@@ -136,15 +166,27 @@ public:
qreal controlY() const;
void setControlY(qreal y);
- void addToPath(QPainterPath &path);
+ qreal relativeControlX() const;
+ void setRelativeControlX(qreal x);
+ bool hasRelativeControlX();
+
+ qreal relativeControlY() const;
+ void setRelativeControlY(qreal y);
+ bool hasRelativeControlY();
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
Q_SIGNALS:
void controlXChanged();
void controlYChanged();
+ void relativeControlXChanged();
+ void relativeControlYChanged();
private:
qreal _controlX;
qreal _controlY;
+ QDeclarativeNullableValue<qreal> _relativeControlX;
+ QDeclarativeNullableValue<qreal> _relativeControlY;
};
class Q_AUTOTEST_EXPORT QDeclarativePathCubic : public QDeclarativeCurve
@@ -155,6 +197,10 @@ class Q_AUTOTEST_EXPORT QDeclarativePathCubic : public QDeclarativeCurve
Q_PROPERTY(qreal control1Y READ control1Y WRITE setControl1Y NOTIFY control1YChanged)
Q_PROPERTY(qreal control2X READ control2X WRITE setControl2X NOTIFY control2XChanged)
Q_PROPERTY(qreal control2Y READ control2Y WRITE setControl2Y NOTIFY control2YChanged)
+ Q_PROPERTY(qreal relativeControl1X READ relativeControl1X WRITE setRelativeControl1X NOTIFY relativeControl1XChanged)
+ Q_PROPERTY(qreal relativeControl1Y READ relativeControl1Y WRITE setRelativeControl1Y NOTIFY relativeControl1YChanged)
+ Q_PROPERTY(qreal relativeControl2X READ relativeControl2X WRITE setRelativeControl2X NOTIFY relativeControl2XChanged)
+ Q_PROPERTY(qreal relativeControl2Y READ relativeControl2Y WRITE setRelativeControl2Y NOTIFY relativeControl2YChanged)
public:
QDeclarativePathCubic(QObject *parent=0) : QDeclarativeCurve(parent), _control1X(0), _control1Y(0), _control2X(0), _control2Y(0) {}
@@ -170,19 +216,113 @@ public:
qreal control2Y() const;
void setControl2Y(qreal y);
- void addToPath(QPainterPath &path);
+ qreal relativeControl1X() const;
+ void setRelativeControl1X(qreal x);
+ bool hasRelativeControl1X();
+
+ qreal relativeControl1Y() const;
+ void setRelativeControl1Y(qreal y);
+ bool hasRelativeControl1Y();
+
+ qreal relativeControl2X() const;
+ void setRelativeControl2X(qreal x);
+ bool hasRelativeControl2X();
+
+ qreal relativeControl2Y() const;
+ void setRelativeControl2Y(qreal y);
+ bool hasRelativeControl2Y();
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
Q_SIGNALS:
void control1XChanged();
void control1YChanged();
void control2XChanged();
void control2YChanged();
+ void relativeControl1XChanged();
+ void relativeControl1YChanged();
+ void relativeControl2XChanged();
+ void relativeControl2YChanged();
private:
qreal _control1X;
qreal _control1Y;
qreal _control2X;
qreal _control2Y;
+ QDeclarativeNullableValue<qreal> _relativeControl1X;
+ QDeclarativeNullableValue<qreal> _relativeControl1Y;
+ QDeclarativeNullableValue<qreal> _relativeControl2X;
+ QDeclarativeNullableValue<qreal> _relativeControl2Y;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathCatmullRomCurve : public QDeclarativeCurve
+{
+ Q_OBJECT
+public:
+ QDeclarativePathCatmullRomCurve(QObject *parent=0) : QDeclarativeCurve(parent) {}
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathArc : public QDeclarativeCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal radiusX READ radiusX WRITE setRadiusX NOTIFY radiusXChanged)
+ Q_PROPERTY(qreal radiusY READ radiusY WRITE setRadiusY NOTIFY radiusYChanged)
+ Q_PROPERTY(bool useLargeArc READ useLargeArc WRITE setUseLargeArc NOTIFY useLargeArcChanged)
+ Q_PROPERTY(ArcDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+public:
+ QDeclarativePathArc(QObject *parent=0)
+ : QDeclarativeCurve(parent), _radiusX(0), _radiusY(0), _useLargeArc(false), _direction(Clockwise) {}
+
+ enum ArcDirection { Clockwise, Counterclockwise };
+ Q_ENUMS(ArcDirection)
+
+ qreal radiusX() const;
+ void setRadiusX(qreal);
+
+ qreal radiusY() const;
+ void setRadiusY(qreal);
+
+ bool useLargeArc() const;
+ void setUseLargeArc(bool);
+
+ ArcDirection direction() const;
+ void setDirection(ArcDirection direction);
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void radiusXChanged();
+ void radiusYChanged();
+ void useLargeArcChanged();
+ void directionChanged();
+
+private:
+ qreal _radiusX;
+ qreal _radiusY;
+ bool _useLargeArc;
+ ArcDirection _direction;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativePathSvg : public QDeclarativeCurve
+{
+ Q_OBJECT
+ Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
+public:
+ QDeclarativePathSvg(QObject *parent=0) : QDeclarativeCurve(parent) {}
+
+ QString path() const;
+ void setPath(const QString &path);
+
+ void addToPath(QPainterPath &path, const QDeclarativePathData &);
+
+Q_SIGNALS:
+ void pathChanged();
+
+private:
+ QString _path;
};
class Q_AUTOTEST_EXPORT QDeclarativePathPercent : public QDeclarativePathElement
@@ -202,6 +342,17 @@ private:
qreal _value;
};
+struct QDeclarativeCachedBezier
+{
+ QDeclarativeCachedBezier() : isValid(false) {}
+ QBezier bezier;
+ int element;
+ qreal bezLength;
+ qreal currLength;
+ qreal p;
+ bool isValid;
+};
+
class QDeclarativePathPrivate;
class Q_AUTOTEST_EXPORT QDeclarativePath : public QObject, public QDeclarativeParserStatus
{
@@ -222,9 +373,11 @@ public:
qreal startX() const;
void setStartX(qreal x);
+ bool hasStartX() const;
qreal startY() const;
void setStartY(qreal y);
+ bool hasStartY() const;
bool isClosed() const;
@@ -232,6 +385,7 @@ public:
QStringList attributes() const;
qreal attributeAt(const QString &, qreal) const;
QPointF pointAt(qreal) const;
+ QPointF sequentialPointAt(qreal p, qreal *angle = 0) const;
Q_SIGNALS:
void changed();
@@ -263,9 +417,19 @@ private:
void endpoint(const QString &name);
void createPointCache() const;
+ static void interpolate(QList<AttributePoint> &points, int idx, const QString &name, qreal value);
+ static void endpoint(QList<AttributePoint> &attributePoints, const QString &name);
+ static QPointF forwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
+ static QPointF backwardsPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
+
private:
Q_DISABLE_COPY(QDeclarativePath)
Q_DECLARE_PRIVATE(QDeclarativePath)
+ friend class QSGPathAnimationUpdater;
+
+public:
+ QPainterPath createPath(const QPointF &startPoint, const QPointF &endPoint, const QStringList &attributes, qreal &pathLength, QList<AttributePoint> &attributePoints, bool *closed = 0);
+ static QPointF sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList<AttributePoint> &attributePoints, QDeclarativeCachedBezier &prevBez, qreal p, qreal *angle = 0);
};
QT_END_NAMESPACE
@@ -276,6 +440,9 @@ QML_DECLARE_TYPE(QDeclarativeCurve)
QML_DECLARE_TYPE(QDeclarativePathLine)
QML_DECLARE_TYPE(QDeclarativePathQuad)
QML_DECLARE_TYPE(QDeclarativePathCubic)
+QML_DECLARE_TYPE(QDeclarativePathCatmullRomCurve)
+QML_DECLARE_TYPE(QDeclarativePathArc)
+QML_DECLARE_TYPE(QDeclarativePathSvg)
QML_DECLARE_TYPE(QDeclarativePathPercent)
QML_DECLARE_TYPE(QDeclarativePath)
diff --git a/src/declarative/util/qdeclarativepath_p_p.h b/src/declarative/util/qdeclarativepath_p_p.h
index 4e407eca35..c7313ea225 100644
--- a/src/declarative/util/qdeclarativepath_p_p.h
+++ b/src/declarative/util/qdeclarativepath_p_p.h
@@ -56,28 +56,33 @@
#include "private/qdeclarativepath_p.h"
#include <qdeclarative.h>
+#include <QtCore/QStringList>
-#include <qstringlist.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
+
class QDeclarativePathPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QDeclarativePath)
public:
- QDeclarativePathPrivate() : startX(0), startY(0), closed(false), componentComplete(true) { }
+ QDeclarativePathPrivate() : pathLength(0), closed(false), componentComplete(true) { }
QPainterPath _path;
QList<QDeclarativePathElement*> _pathElements;
mutable QVector<QPointF> _pointCache;
QList<QDeclarativePath::AttributePoint> _attributePoints;
QStringList _attributes;
- int startX;
- int startY;
+ QList<QDeclarativeCurve*> _pathCurves;
+ mutable QDeclarativeCachedBezier prevBez;
+ QDeclarativeNullableValue<qreal> startX;
+ QDeclarativeNullableValue<qreal> startY;
+ qreal pathLength;
bool closed;
bool componentComplete;
};
QT_END_NAMESPACE
+
#endif
diff --git a/src/declarative/util/qdeclarativepathinterpolator.cpp b/src/declarative/util/qdeclarativepathinterpolator.cpp
new file mode 100644
index 0000000000..db6ef155b7
--- /dev/null
+++ b/src/declarative/util/qdeclarativepathinterpolator.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qdeclarativepathinterpolator_p.h"
+
+#include "private/qdeclarativepath_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativePathInterpolator::QDeclarativePathInterpolator(QObject *parent) :
+ QObject(parent), _path(0), _x(0), _y(0), _angle(0), _progress(0)
+{
+}
+
+QDeclarativePath *QDeclarativePathInterpolator::path() const
+{
+ return _path;
+}
+
+void QDeclarativePathInterpolator::setPath(QDeclarativePath *path)
+{
+ if (_path == path)
+ return;
+ if (_path)
+ disconnect(_path, SIGNAL(changed()), this, SLOT(_q_pathUpdated()));
+ _path = path;
+ connect(_path, SIGNAL(changed()), this, SLOT(_q_pathUpdated()));
+ emit pathChanged();
+}
+
+qreal QDeclarativePathInterpolator::progress() const
+{
+ return _progress;
+}
+
+void QDeclarativePathInterpolator::setProgress(qreal progress)
+{
+ if (progress == _progress)
+ return;
+ _progress = progress;
+ emit progressChanged();
+ _q_pathUpdated();
+}
+
+qreal QDeclarativePathInterpolator::x() const
+{
+ return _x;
+}
+
+qreal QDeclarativePathInterpolator::y() const
+{
+ return _y;
+}
+
+qreal QDeclarativePathInterpolator::angle() const
+{
+ return _angle;
+}
+
+void QDeclarativePathInterpolator::_q_pathUpdated()
+{
+ if (! _path)
+ return;
+
+ qreal angle = 0;
+ const QPointF pt = _path->sequentialPointAt(_progress, &angle);
+
+ if (_x != pt.x()) {
+ _x = pt.x();
+ emit xChanged();
+ }
+
+ if (_y != pt.y()) {
+ _y = pt.y();
+ emit yChanged();
+ }
+
+ if (angle != _angle) {
+ _angle = angle;
+ emit angleChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativepathinterpolator_p.h b/src/declarative/util/qdeclarativepathinterpolator_p.h
new file mode 100644
index 0000000000..cb8ccfa8fb
--- /dev/null
+++ b/src/declarative/util/qdeclarativepathinterpolator_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 QDECLARATIVEPATHINTERPOLATOR_P_H
+#define QDECLARATIVEPATHINTERPOLATOR_P_H
+
+#include <qdeclarative.h>
+#include <QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativePath;
+class Q_AUTOTEST_EXPORT QDeclarativePathInterpolator : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
+ Q_PROPERTY(qreal x READ x NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y NOTIFY yChanged)
+ Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged)
+public:
+ explicit QDeclarativePathInterpolator(QObject *parent = 0);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *path);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ qreal x() const;
+ qreal y() const;
+ qreal angle() const;
+
+Q_SIGNALS:
+ void pathChanged();
+ void progressChanged();
+ void xChanged();
+ void yChanged();
+ void angleChanged();
+
+private Q_SLOTS:
+ void _q_pathUpdated();
+
+private:
+ QDeclarativePath *_path;
+ qreal _x;
+ qreal _y;
+ qreal _angle;
+ qreal _progress;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePathInterpolator)
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEPATHINTERPOLATOR_P_H
diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp
index c9242672c5..fc009a8a36 100644
--- a/src/declarative/util/qdeclarativepropertymap.cpp
+++ b/src/declarative/util/qdeclarativepropertymap.cpp
@@ -58,7 +58,7 @@ public:
protected:
virtual void propertyWritten(int index);
virtual void propertyCreated(int, QMetaPropertyBuilder &);
-
+ virtual int createProperty(const char *, const char *);
private:
QDeclarativePropertyMap *map;
QDeclarativePropertyMapPrivate *priv;
@@ -71,8 +71,19 @@ public:
QDeclarativePropertyMapMetaObject *mo;
QStringList keys;
void emitChanged(const QString &key, const QVariant &value);
+ bool validKeyName(const QString& name);
};
+bool QDeclarativePropertyMapPrivate::validKeyName(const QString& name)
+{
+ //The following strings shouldn't be used as property names
+ return name != QLatin1String("keys")
+ && name != QLatin1String("valueChanged")
+ && name != QLatin1String("QObject")
+ && name != QLatin1String("destroyed")
+ && name != QLatin1String("deleteLater");
+}
+
void QDeclarativePropertyMapPrivate::emitChanged(const QString &key, const QVariant &value)
{
Q_Q(QDeclarativePropertyMap);
@@ -95,6 +106,13 @@ void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilde
priv->keys.append(QString::fromUtf8(b.name()));
}
+int QDeclarativePropertyMapMetaObject::createProperty(const char *name, const char *value)
+{
+ if (!priv->validKeyName(name))
+ return -1;
+ return QDeclarativeOpenMetaObject::createProperty(name, value);
+}
+
/*!
\class QDeclarativePropertyMap
\brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in QML bindings.
@@ -181,12 +199,8 @@ QVariant QDeclarativePropertyMap::value(const QString &key) const
void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value)
{
Q_D(QDeclarativePropertyMap);
- //The following strings shouldn't be used as property names
- if (key != QLatin1String("keys")
- && key != QLatin1String("valueChanged")
- && key != QLatin1String("QObject")
- && key != QLatin1String("destroyed")
- && key != QLatin1String("deleteLater")) {
+
+ if (d->validKeyName(key)) {
d->mo->setValue(key.toUtf8(), value);
} else {
qWarning() << "Creating property with name"
diff --git a/src/declarative/util/qdeclarativestyledtext.cpp b/src/declarative/util/qdeclarativestyledtext.cpp
index a00c979d7c..b3d6c877c4 100644
--- a/src/declarative/util/qdeclarativestyledtext.cpp
+++ b/src/declarative/util/qdeclarativestyledtext.cpp
@@ -53,7 +53,12 @@
<b></b> - bold
<i></i> - italic
<br> - new line
+ <p> - paragraph
+ <u> - underlined text
<font color="color_name" size="1-7"></font>
+ <h1> to <h6> - headers
+ <a href=""> - anchor
+ <ol type="">, <ul type=""> and <li> - ordered and unordered lists
The opening and closing tags must be correctly nested.
*/
@@ -63,13 +68,28 @@ QT_BEGIN_NAMESPACE
class QDeclarativeStyledTextPrivate
{
public:
- QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l) : text(t), layout(l), baseFont(layout.font()) {}
+ enum ListType { Ordered, Unordered };
+ enum ListFormat { Bullet, Disc, Square, Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman };
+
+ struct List {
+ int level;
+ ListType type;
+ ListFormat format;
+ };
+
+ QDeclarativeStyledTextPrivate(const QString &t, QTextLayout &l)
+ : text(t), layout(l), baseFont(layout.font()), hasNewLine(false)
+ {
+ }
void parse();
bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format);
- bool parseCloseTag(const QChar *&ch, const QString &textIn);
+ bool parseCloseTag(const QChar *&ch, const QString &textIn, QString &textOut);
void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut);
bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
+ bool parseOrderedListAttributes(const QChar *&ch, const QString &textIn);
+ bool parseUnorderedListAttributes(const QChar *&ch, const QString &textIn);
+ bool parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
QStringRef parseValue(const QChar *&ch, const QString &textIn);
@@ -78,9 +98,14 @@ public:
++ch;
}
+ static QString toAlpha(int value, bool upper);
+ static QString toRoman(int value, bool upper);
+
QString text;
QTextLayout &layout;
QFont baseFont;
+ QStack<List> listStack;
+ bool hasNewLine;
static const QChar lessThan;
static const QChar greaterThan;
@@ -89,6 +114,10 @@ public:
static const QChar doubleQuote;
static const QChar slash;
static const QChar ampersand;
+ static const QChar bullet;
+ static const QChar disc;
+ static const QChar square;
+ static const int tabsize = 6;
};
const QChar QDeclarativeStyledTextPrivate::lessThan(QLatin1Char('<'));
@@ -98,6 +127,9 @@ const QChar QDeclarativeStyledTextPrivate::singleQuote(QLatin1Char('\''));
const QChar QDeclarativeStyledTextPrivate::doubleQuote(QLatin1Char('\"'));
const QChar QDeclarativeStyledTextPrivate::slash(QLatin1Char('/'));
const QChar QDeclarativeStyledTextPrivate::ampersand(QLatin1Char('&'));
+const QChar QDeclarativeStyledTextPrivate::bullet(0x2022);
+const QChar QDeclarativeStyledTextPrivate::disc(0x25e6);
+const QChar QDeclarativeStyledTextPrivate::square(0x25a1);
QDeclarativeStyledText::QDeclarativeStyledText(const QString &string, QTextLayout &layout)
: d(new QDeclarativeStyledTextPrivate(string, layout))
@@ -131,8 +163,19 @@ void QDeclarativeStyledTextPrivate::parse()
const QChar *ch = text.constData();
while (!ch->isNull()) {
if (*ch == lessThan) {
- if (textLength)
- drawText.append(QStringRef(&text, textStart, textLength));
+ if (textLength) {
+ QStringRef ref = QStringRef(&text, textStart, textLength);
+ const QChar *c = ref.constData();
+ bool isWhiteSpace = true;
+ for (int i = 0; isWhiteSpace && (i < textLength); ++c, ++i) {
+ if (!c->isSpace())
+ isWhiteSpace = false;
+ }
+ if (!isWhiteSpace) {
+ drawText.append(ref);
+ hasNewLine = false;
+ }
+ }
if (rangeStart != drawText.length() && formatStack.count()) {
QTextLayout::FormatRange formatRange;
formatRange.format = formatStack.top();
@@ -144,7 +187,7 @@ void QDeclarativeStyledTextPrivate::parse()
++ch;
if (*ch == slash) {
++ch;
- if (parseCloseTag(ch, text)) {
+ if (parseCloseTag(ch, text, drawText)) {
if (formatStack.count())
formatStack.pop();
}
@@ -203,6 +246,71 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te
} else if (char0 == QLatin1Char('i')) {
if (tagLength == 1)
format.setFontItalic(true);
+ } else if (char0 == QLatin1Char('p')) {
+ if (tagLength == 1) {
+ if (!hasNewLine)
+ textOut.append(QChar::LineSeparator);
+ }
+ } else if (char0 == QLatin1Char('u')) {
+ if (tagLength == 1)
+ format.setFontUnderline(true);
+ else if (tag == QLatin1String("ul")) {
+ List listItem;
+ listItem.level = 0;
+ listItem.type = Unordered;
+ listItem.format = Bullet;
+ listStack.push(listItem);
+ }
+ } else if (char0 == QLatin1Char('h') && tagLength == 2) {
+ int level = tag.at(1).digitValue();
+ if (level >= 1 && level <= 6) {
+ static const qreal scaling[] = { 2.0, 1.5, 1.2, 1.0, 0.8, 0.7 };
+ if (!hasNewLine)
+ textOut.append(QChar::LineSeparator);
+ format.setFontPointSize(baseFont.pointSize() * scaling[level - 1]);
+ format.setFontWeight(QFont::Bold);
+ }
+ } else if (tag == QLatin1String("ol")) {
+ List listItem;
+ listItem.level = 0;
+ listItem.type = Ordered;
+ listItem.format = Decimal;
+ listStack.push(listItem);
+ } else if (tag == QLatin1String("li")) {
+ if (!hasNewLine)
+ textOut.append(QChar(QChar::LineSeparator));
+ if (!listStack.isEmpty()) {
+ int count = ++listStack.top().level;
+ for (int i = 0; i < listStack.size(); ++i)
+ textOut += QString(tabsize, QChar::Nbsp);
+ switch (listStack.top().format) {
+ case Decimal:
+ textOut += QString::number(count) % QLatin1Char('.');
+ break;
+ case LowerAlpha:
+ textOut += toAlpha(count, false) % QLatin1Char('.');
+ break;
+ case UpperAlpha:
+ textOut += toAlpha(count, true) % QLatin1Char('.');
+ break;
+ case LowerRoman:
+ textOut += toRoman(count, false) % QLatin1Char('.');
+ break;
+ case UpperRoman:
+ textOut += toRoman(count, true) % QLatin1Char('.');
+ break;
+ case Bullet:
+ textOut += bullet;
+ break;
+ case Disc:
+ textOut += disc;
+ break;
+ case Square:
+ textOut += square;
+ break;
+ }
+ textOut += QString(2, QChar::Nbsp);
+ }
}
return true;
} else if (ch->isSpace()) {
@@ -210,18 +318,24 @@ bool QDeclarativeStyledTextPrivate::parseTag(const QChar *&ch, const QString &te
QStringRef tag(&textIn, tagStart, tagLength);
if (tag == QLatin1String("font"))
return parseFontAttributes(ch, textIn, format);
+ if (tag == QLatin1String("ol"))
+ return parseOrderedListAttributes(ch, textIn);
+ if (tag == QLatin1String("ul"))
+ return parseUnorderedListAttributes(ch, textIn);
+ if (tag == QLatin1String("a")) {
+ return parseAnchorAttributes(ch, textIn, format);
+ }
if (*ch == greaterThan || ch->isNull())
continue;
- } else if (*ch != slash){
+ } else if (*ch != slash) {
tagLength++;
}
++ch;
}
-
return false;
}
-bool QDeclarativeStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn)
+bool QDeclarativeStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn, QString &textOut)
{
skipSpace(ch);
@@ -231,6 +345,7 @@ bool QDeclarativeStyledTextPrivate::parseCloseTag(const QChar *&ch, const QStrin
if (*ch == greaterThan) {
QStringRef tag(&textIn, tagStart, tagLength);
const QChar char0 = tag.at(0);
+ hasNewLine = false;
if (char0 == QLatin1Char('b')) {
if (tagLength == 1)
return true;
@@ -239,8 +354,41 @@ bool QDeclarativeStyledTextPrivate::parseCloseTag(const QChar *&ch, const QStrin
} else if (char0 == QLatin1Char('i')) {
if (tagLength == 1)
return true;
+ } else if (char0 == QLatin1Char('a')) {
+ if (tagLength == 1)
+ return true;
+ } else if (char0 == QLatin1Char('p')) {
+ if (tagLength == 1) {
+ textOut.append(QChar::LineSeparator);
+ hasNewLine = true;
+ return true;
+ }
+ } else if (char0 == QLatin1Char('u')) {
+ if (tagLength == 1)
+ return true;
+ else if (tag == QLatin1String("ul")) {
+ if (!listStack.isEmpty()) {
+ listStack.pop();
+ if (!listStack.count())
+ textOut.append(QChar::LineSeparator);
+ }
+ return true;
+ }
+ } else if (char0 == QLatin1Char('h') && tagLength == 2) {
+ textOut.append(QChar::LineSeparator);
+ hasNewLine = true;
+ return true;
} else if (tag == QLatin1String("font")) {
return true;
+ } else if (tag == QLatin1String("ol")) {
+ if (!listStack.isEmpty()) {
+ listStack.pop();
+ if (!listStack.count())
+ textOut.append(QChar::LineSeparator);
+ }
+ return true;
+ } else if (tag == QLatin1String("li")) {
+ return true;
}
return false;
} else if (!ch->isSpace()){
@@ -296,6 +444,79 @@ bool QDeclarativeStyledTextPrivate::parseFontAttributes(const QChar *&ch, const
return valid;
}
+bool QDeclarativeStyledTextPrivate::parseOrderedListAttributes(const QChar *&ch, const QString &textIn)
+{
+ bool valid = false;
+
+ List listItem;
+ listItem.level = 0;
+ listItem.type = Ordered;
+ listItem.format = Decimal;
+
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("type")) {
+ valid = true;
+ if (attr.second == QLatin1String("a"))
+ listItem.format = LowerAlpha;
+ else if (attr.second == QLatin1String("A"))
+ listItem.format = UpperAlpha;
+ else if (attr.second == QLatin1String("i"))
+ listItem.format = LowerRoman;
+ else if (attr.second == QLatin1String("I"))
+ listItem.format = UpperRoman;
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ listStack.push(listItem);
+ return valid;
+}
+
+bool QDeclarativeStyledTextPrivate::parseUnorderedListAttributes(const QChar *&ch, const QString &textIn)
+{
+ bool valid = false;
+
+ List listItem;
+ listItem.level = 0;
+ listItem.type = Unordered;
+ listItem.format = Bullet;
+
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("type")) {
+ valid = true;
+ if (attr.second == QLatin1String("disc"))
+ listItem.format = Disc;
+ else if (attr.second == QLatin1String("square"))
+ listItem.format = Square;
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ listStack.push(listItem);
+ return valid;
+}
+
+bool QDeclarativeStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format)
+{
+ bool valid = false;
+
+ QPair<QStringRef,QStringRef> attr;
+ do {
+ attr = parseAttribute(ch, textIn);
+ if (attr.first == QLatin1String("href")) {
+ format.setAnchorHref(attr.second.toString());
+ format.setAnchor(true);
+ format.setFontUnderline(true);
+ format.setForeground(QColor("blue"));
+ valid = true;
+ }
+ } while (!ch->isNull() && !attr.first.isEmpty());
+
+ return valid;
+}
+
QPair<QStringRef,QStringRef> QDeclarativeStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
{
skipSpace(ch);
@@ -344,4 +565,56 @@ QStringRef QDeclarativeStyledTextPrivate::parseValue(const QChar *&ch, const QSt
return QStringRef(&textIn, valStart, valLength);
}
+QString QDeclarativeStyledTextPrivate::toAlpha(int value, bool upper)
+{
+ const char baseChar = upper ? 'A' : 'a';
+
+ QString result;
+ int c = value;
+ while (c > 0) {
+ c--;
+ result.prepend(QChar(baseChar + (c % 26)));
+ c /= 26;
+ }
+ return result;
+}
+
+QString QDeclarativeStyledTextPrivate::toRoman(int value, bool upper)
+{
+ QString result = QLatin1String("?");
+ // works for up to 4999 items
+ if (value < 5000) {
+ QByteArray romanNumeral;
+
+ static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
+ static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
+ QByteArray romanSymbols;
+ if (!upper)
+ romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
+ else
+ romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
+
+ int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
+ int n = value;
+ for (int i = 12; i >= 0; n %= c[i], i--) {
+ int q = n / c[i];
+ if (q > 0) {
+ int startDigit = i + (i + 3) / 4;
+ int numDigits;
+ if (i % 4) {
+ if ((i - 2) % 4)
+ numDigits = 2;
+ else
+ numDigits = 1;
+ }
+ else
+ numDigits = q;
+ romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
+ }
+ }
+ result = QString::fromLatin1(romanNumeral);
+ }
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativesvgparser.cpp b/src/declarative/util/qdeclarativesvgparser.cpp
new file mode 100644
index 0000000000..36714d7a38
--- /dev/null
+++ b/src/declarative/util/qdeclarativesvgparser.cpp
@@ -0,0 +1,633 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclaractive 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 "qdeclarativesvgparser_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+static const double Q_PI = 3.14159265358979323846; // pi
+
+//copied from QtSvg (qsvghandler.cpp).
+Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
+// '0' is 0x30 and '9' is 0x39
+static inline bool isDigit(ushort ch)
+{
+ static quint16 magic = 0x3ff;
+ return ((ch >> 4) == 3) && (magic >> (ch & 15));
+}
+
+static qreal toDouble(const QChar *&str)
+{
+ const int maxLen = 255;//technically doubles can go til 308+ but whatever
+ char temp[maxLen+1];
+ int pos = 0;
+
+ if (*str == QLatin1Char('-')) {
+ temp[pos++] = '-';
+ ++str;
+ } else if (*str == QLatin1Char('+')) {
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ if (*str == QLatin1Char('.') && pos < maxLen) {
+ temp[pos++] = '.';
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ bool exponent = false;
+ if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
+ exponent = true;
+ temp[pos++] = 'e';
+ ++str;
+ if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ while (isDigit(str->unicode()) && pos < maxLen) {
+ temp[pos++] = str->toLatin1();
+ ++str;
+ }
+ }
+
+ temp[pos] = '\0';
+
+ qreal val;
+ if (!exponent && pos < 10) {
+ int ival = 0;
+ const char *t = temp;
+ bool neg = false;
+ if(*t == '-') {
+ neg = true;
+ ++t;
+ }
+ while(*t && *t != '.') {
+ ival *= 10;
+ ival += (*t) - '0';
+ ++t;
+ }
+ if(*t == '.') {
+ ++t;
+ int div = 1;
+ while(*t) {
+ ival *= 10;
+ ival += (*t) - '0';
+ div *= 10;
+ ++t;
+ }
+ val = ((qreal)ival)/((qreal)div);
+ } else {
+ val = ival;
+ }
+ if (neg)
+ val = -val;
+ } else {
+#if defined(Q_WS_QWS) && !defined(Q_OS_VXWORKS)
+ if(sizeof(qreal) == sizeof(float))
+ val = strtof(temp, 0);
+ else
+#endif
+ {
+ bool ok = false;
+ val = qstrtod(temp, 0, &ok);
+ }
+ }
+ return val;
+
+}
+static qreal toDouble(const QString &str, bool *ok = NULL)
+{
+ const QChar *c = str.constData();
+ qreal res = toDouble(c);
+ if (ok) {
+ *ok = ((*c) == QLatin1Char('\0'));
+ }
+ return res;
+}
+
+static qreal toDouble(const QStringRef &str, bool *ok = NULL)
+{
+ const QChar *c = str.constData();
+ qreal res = toDouble(c);
+ if (ok) {
+ *ok = (c == (str.constData() + str.length()));
+ }
+ return res;
+}
+static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
+{
+ while (str->isSpace())
+ ++str;
+ while (isDigit(str->unicode()) ||
+ *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
+ *str == QLatin1Char('.')) {
+
+ points.append(toDouble(str));
+
+ while (str->isSpace())
+ ++str;
+ if (*str == QLatin1Char(','))
+ ++str;
+
+ //eat the rest of space
+ while (str->isSpace())
+ ++str;
+ }
+}
+
+static void pathArcSegment(QPainterPath &path,
+ qreal xc, qreal yc,
+ qreal th0, qreal th1,
+ qreal rx, qreal ry, qreal xAxisRotation)
+{
+ qreal sinTh, cosTh;
+ qreal a00, a01, a10, a11;
+ qreal x1, y1, x2, y2, x3, y3;
+ qreal t;
+ qreal thHalf;
+
+ sinTh = qSin(xAxisRotation * (Q_PI / 180.0));
+ cosTh = qCos(xAxisRotation * (Q_PI / 180.0));
+
+ a00 = cosTh * rx;
+ a01 = -sinTh * ry;
+ a10 = sinTh * rx;
+ a11 = cosTh * ry;
+
+ thHalf = 0.5 * (th1 - th0);
+ t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
+ x1 = xc + qCos(th0) - t * qSin(th0);
+ y1 = yc + qSin(th0) + t * qCos(th0);
+ x3 = xc + qCos(th1);
+ y3 = yc + qSin(th1);
+ x2 = x3 + t * qSin(th1);
+ y2 = y3 - t * qCos(th1);
+
+ path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
+ a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
+ a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
+}
+
+void QDeclarativeSvgParser::pathArc(QPainterPath &path,
+ qreal rx,
+ qreal ry,
+ qreal x_axis_rotation,
+ int large_arc_flag,
+ int sweep_flag,
+ qreal x,
+ qreal y,
+ qreal curx, qreal cury)
+{
+ qreal sin_th, cos_th;
+ qreal a00, a01, a10, a11;
+ qreal x0, y0, x1, y1, xc, yc;
+ qreal d, sfactor, sfactor_sq;
+ qreal th0, th1, th_arc;
+ int i, n_segs;
+ qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
+
+ rx = qAbs(rx);
+ ry = qAbs(ry);
+
+ sin_th = qSin(x_axis_rotation * (Q_PI / 180.0));
+ cos_th = qCos(x_axis_rotation * (Q_PI / 180.0));
+
+ dx = (curx - x) / 2.0;
+ dy = (cury - y) / 2.0;
+ dx1 = cos_th * dx + sin_th * dy;
+ dy1 = -sin_th * dx + cos_th * dy;
+ Pr1 = rx * rx;
+ Pr2 = ry * ry;
+ Px = dx1 * dx1;
+ Py = dy1 * dy1;
+ /* Spec : check if radii are large enough */
+ check = Px / Pr1 + Py / Pr2;
+ if (check > 1) {
+ rx = rx * qSqrt(check);
+ ry = ry * qSqrt(check);
+ }
+
+ a00 = cos_th / rx;
+ a01 = sin_th / rx;
+ a10 = -sin_th / ry;
+ a11 = cos_th / ry;
+ x0 = a00 * curx + a01 * cury;
+ y0 = a10 * curx + a11 * cury;
+ x1 = a00 * x + a01 * y;
+ y1 = a10 * x + a11 * y;
+ /* (x0, y0) is current point in transformed coordinate space.
+ (x1, y1) is new point in transformed coordinate space.
+
+ The arc fits a unit-radius circle in this space.
+ */
+ d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
+ sfactor_sq = 1.0 / d - 0.25;
+ if (sfactor_sq < 0) sfactor_sq = 0;
+ sfactor = qSqrt(sfactor_sq);
+ if (sweep_flag == large_arc_flag) sfactor = -sfactor;
+ xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
+ yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
+ /* (xc, yc) is center of the circle. */
+
+ th0 = qAtan2(y0 - yc, x0 - xc);
+ th1 = qAtan2(y1 - yc, x1 - xc);
+
+ th_arc = th1 - th0;
+ if (th_arc < 0 && sweep_flag)
+ th_arc += 2 * Q_PI;
+ else if (th_arc > 0 && !sweep_flag)
+ th_arc -= 2 * Q_PI;
+
+ n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
+
+ for (i = 0; i < n_segs; i++) {
+ pathArcSegment(path, xc, yc,
+ th0 + i * th_arc / n_segs,
+ th0 + (i + 1) * th_arc / n_segs,
+ rx, ry, x_axis_rotation);
+ }
+}
+
+
+bool QDeclarativeSvgParser::parsePathDataFast(const QString &dataStr, QPainterPath &path)
+{
+ qreal x0 = 0, y0 = 0; // starting point
+ qreal x = 0, y = 0; // current point
+ char lastMode = 0;
+ QPointF ctrlPt;
+ const QChar *str = dataStr.constData();
+ const QChar *end = str + dataStr.size();
+
+ while (str != end) {
+ while (str->isSpace())
+ ++str;
+ QChar pathElem = *str;
+ ++str;
+ QChar endc = *end;
+ *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
+ QVarLengthArray<qreal, 8> arg;
+ parseNumbersArray(str, arg);
+ *const_cast<QChar *>(end) = endc;
+ if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
+ arg.append(0);//dummy
+ const qreal *num = arg.constData();
+ int count = arg.count();
+ while (count > 0) {
+ qreal offsetX = x; // correction offsets
+ qreal offsetY = y; // for relative commands
+ switch (pathElem.unicode()) {
+ case 'm': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = x0 = num[0] + offsetX;
+ y = y0 = num[1] + offsetY;
+ num += 2;
+ count -= 2;
+ path.moveTo(x0, y0);
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('l');
+ }
+ break;
+ case 'M': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = x0 = num[0];
+ y = y0 = num[1];
+ num += 2;
+ count -= 2;
+ path.moveTo(x0, y0);
+
+ // As per 1.2 spec 8.3.2 The "moveto" commands
+ // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
+ // the subsequent pairs shall be treated as implicit 'lineto' commands.
+ pathElem = QLatin1Char('L');
+ }
+ break;
+ case 'z':
+ case 'Z': {
+ x = x0;
+ y = y0;
+ count--; // skip dummy
+ num++;
+ path.closeSubpath();
+ }
+ break;
+ case 'l': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = num[0] + offsetX;
+ y = num[1] + offsetY;
+ num += 2;
+ count -= 2;
+ path.lineTo(x, y);
+
+ }
+ break;
+ case 'L': {
+ if (count < 2) {
+ num++;
+ count--;
+ break;
+ }
+ x = num[0];
+ y = num[1];
+ num += 2;
+ count -= 2;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'h': {
+ x = num[0] + offsetX;
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'H': {
+ x = num[0];
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'v': {
+ y = num[0] + offsetY;
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'V': {
+ y = num[0];
+ num++;
+ count--;
+ path.lineTo(x, y);
+ }
+ break;
+ case 'c': {
+ if (count < 6) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1(num[0] + offsetX, num[1] + offsetY);
+ QPointF c2(num[2] + offsetX, num[3] + offsetY);
+ QPointF e(num[4] + offsetX, num[5] + offsetY);
+ num += 6;
+ count -= 6;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'C': {
+ if (count < 6) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1(num[0], num[1]);
+ QPointF c2(num[2], num[3]);
+ QPointF e(num[4], num[5]);
+ num += 6;
+ count -= 6;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 's': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1;
+ if (lastMode == 'c' || lastMode == 'C' ||
+ lastMode == 's' || lastMode == 'S')
+ c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c1 = QPointF(x, y);
+ QPointF c2(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'S': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c1;
+ if (lastMode == 'c' || lastMode == 'C' ||
+ lastMode == 's' || lastMode == 'S')
+ c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c1 = QPointF(x, y);
+ QPointF c2(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
+ path.cubicTo(c1, c2, e);
+ ctrlPt = c2;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'q': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c(num[0] + offsetX, num[1] + offsetY);
+ QPointF e(num[2] + offsetX, num[3] + offsetY);
+ num += 4;
+ count -= 4;
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'Q': {
+ if (count < 4) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF c(num[0], num[1]);
+ QPointF e(num[2], num[3]);
+ num += 4;
+ count -= 4;
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 't': {
+ if (count < 2) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF e(num[0] + offsetX, num[1] + offsetY);
+ num += 2;
+ count -= 2;
+ QPointF c;
+ if (lastMode == 'q' || lastMode == 'Q' ||
+ lastMode == 't' || lastMode == 'T')
+ c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c = QPointF(x, y);
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'T': {
+ if (count < 2) {
+ num += count;
+ count = 0;
+ break;
+ }
+ QPointF e(num[0], num[1]);
+ num += 2;
+ count -= 2;
+ QPointF c;
+ if (lastMode == 'q' || lastMode == 'Q' ||
+ lastMode == 't' || lastMode == 'T')
+ c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
+ else
+ c = QPointF(x, y);
+ path.quadTo(c, e);
+ ctrlPt = c;
+ x = e.x();
+ y = e.y();
+ break;
+ }
+ case 'a': {
+ if (count < 7) {
+ num += count;
+ count = 0;
+ break;
+ }
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++) + offsetX;
+ qreal ey = (*num++) + offsetY;
+ count -= 7;
+ qreal curx = x;
+ qreal cury = y;
+ pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
+ int(sweepFlag), ex, ey, curx, cury);
+
+ x = ex;
+ y = ey;
+ }
+ break;
+ case 'A': {
+ if (count < 7) {
+ num += count;
+ count = 0;
+ break;
+ }
+ qreal rx = (*num++);
+ qreal ry = (*num++);
+ qreal xAxisRotation = (*num++);
+ qreal largeArcFlag = (*num++);
+ qreal sweepFlag = (*num++);
+ qreal ex = (*num++);
+ qreal ey = (*num++);
+ count -= 7;
+ qreal curx = x;
+ qreal cury = y;
+ pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
+ int(sweepFlag), ex, ey, curx, cury);
+
+ x = ex;
+ y = ey;
+ }
+ break;
+ default:
+ return false;
+ }
+ lastMode = pathElem.toLatin1();
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/particles/qsgkill.cpp b/src/declarative/util/qdeclarativesvgparser_p.h
index dfd26e3f39..0d7be10761 100644
--- a/src/declarative/particles/qsgkill.cpp
+++ b/src/declarative/util/qdeclarativesvgparser_p.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the Declarative module of the Qt Toolkit.
+** This file is part of the QtDeclaractive module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,30 +39,22 @@
**
****************************************************************************/
-#include "qsgkill_p.h"
-#include "qsgparticleemitter_p.h"
-QT_BEGIN_NAMESPACE
-/*!
- \qmlclass Kill QSGKillAffector
- \inqmlmodule QtQuick.Particles 2
- \inherits Affector
- \brief The Kill affector allows you to expire affected particles
-
-*/
+#ifndef QDECLARATIVESVGPARSER_P_H
+#define QDECLARATIVESVGPARSER_P_H
-QSGKillAffector::QSGKillAffector(QSGItem *parent) :
- QSGParticleAffector(parent)
-{
-}
+#include <QtCore/qstring.h>
+#include <QtGui/qpainterpath.h>
+QT_BEGIN_NAMESPACE
-bool QSGKillAffector::affectParticle(QSGParticleData *d, qreal dt)
+namespace QDeclarativeSvgParser
{
- Q_UNUSED(dt);
- if (d->stillAlive()){
- d->t -= d->lifeSpan + 1;
- return true;
- }
- return false;
+ bool parsePathDataFast(const QString &dataStr, QPainterPath &path);
+ void pathArc(QPainterPath &path, qreal rx, qreal ry, qreal x_axis_rotation,
+ int large_arc_flag, int sweep_flag, qreal x, qreal y, qreal curx,
+ qreal cury);
}
+
QT_END_NAMESPACE
+
+#endif // QDECLARATIVESVGPARSER_P_H
diff --git a/src/declarative/util/qdeclarativetransitionmanager.cpp b/src/declarative/util/qdeclarativetransitionmanager.cpp
index 0b549b7cf7..30504cb241 100644
--- a/src/declarative/util/qdeclarativetransitionmanager.cpp
+++ b/src/declarative/util/qdeclarativetransitionmanager.cpp
@@ -119,7 +119,7 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> &
cancel();
QDeclarativeStateOperation::ActionList applyList = list;
- // Determine which actions are binding changes.
+ // Determine which actions are binding changes and disable any current bindings
foreach(const QDeclarativeAction &action, applyList) {
if (action.toBinding)
d->bindingsList << action;
@@ -139,8 +139,11 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> &
//
// This doesn't catch everything, and it might be a little fragile in
// some cases - but whatcha going to do?
+ //
+ // Note that we only fast forward if both a transition and bindings are
+ // present, as it is unneccessary (and potentially expensive) otherwise.
- if (!d->bindingsList.isEmpty()) {
+ if (transition && !d->bindingsList.isEmpty()) {
// Apply all the property and binding changes
for (int ii = 0; ii < applyList.size(); ++ii) {
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index 965acf80c6..ddd702609c 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -29,7 +29,9 @@ SOURCES += \
$$PWD/qdeclarativelistmodelworkeragent.cpp \
$$PWD/qdeclarativepath.cpp \
$$PWD/qdeclarativechangeset.cpp \
- $$PWD/qlistmodelinterface.cpp
+ $$PWD/qlistmodelinterface.cpp \
+ $$PWD/qdeclarativepathinterpolator.cpp \
+ $$PWD/qdeclarativesvgparser.cpp
HEADERS += \
$$PWD/qdeclarativeapplication_p.h \
@@ -65,7 +67,9 @@ HEADERS += \
$$PWD/qdeclarativepath_p.h \
$$PWD/qdeclarativepath_p_p.h \
$$PWD/qdeclarativechangeset_p.h \
- $$PWD/qlistmodelinterface_p.h
+ $$PWD/qlistmodelinterface_p.h \
+ $$PWD/qdeclarativepathinterpolator_p.h \
+ $$PWD/qdeclarativesvgparser_p.h
contains(QT_CONFIG, xmlpatterns) {
QT+=xmlpatterns
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 6da66b20de..ed8bf55d6b 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -145,7 +145,6 @@ Item {
if ("mapFromItem" in o && "mapToItem" in o) {
return "declarativeitem"; // @todo improve detection of declarative items
} else if ("x" in o && "y" in o && "z" in o) {
- console.log("typeof debug:" + o);
return "vector3d"; // Qt3D vector
}
return "object";
@@ -693,4 +692,4 @@ Item {
if (when && !completed && !running)
qtest_run()
}
-}
+} \ No newline at end of file
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 80c3f8b3d5..40b7d9bea8 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -78,7 +78,6 @@ public:
}
QByteArray intern(const QString &str);
- void updateTestObjectName();
QString testCaseName;
QString functionName;
@@ -96,25 +95,6 @@ QByteArray QuickTestResultPrivate::intern(const QString &str)
return *(internedStrings.insert(bstr));
}
-void QuickTestResultPrivate::updateTestObjectName()
-{
- // In plain logging mode we use the TestCase name as the
- // class name so that multiple TestCase elements will report
- // results with "testCase::function". In XML logging mode,
- // we use the program name as the class name and report test
- // functions as "testCase__function".
- if (QTestLog::logMode() == QTestLog::Plain) {
- if (testCaseName.isEmpty()) {
- QTestResult::setCurrentTestObject(globalProgramName);
- } else if (QTestLog::logMode() == QTestLog::Plain) {
- QTestResult::setCurrentTestObject
- (intern(testCaseName).constData());
- }
- } else {
- QTestResult::setCurrentTestObject(globalProgramName);
- }
-}
-
QuickTestResult::QuickTestResult(QObject *parent)
: QObject(parent), d_ptr(new QuickTestResultPrivate)
{
@@ -144,7 +124,6 @@ void QuickTestResult::setTestCaseName(const QString &name)
{
Q_D(QuickTestResult);
d->testCaseName = name;
- d->updateTestObjectName();
emit testCaseNameChanged();
}
@@ -167,15 +146,11 @@ void QuickTestResult::setFunctionName(const QString &name)
{
Q_D(QuickTestResult);
if (!name.isEmpty()) {
- // In plain logging mode, we use the function name directly.
- // In XML logging mode, we use "testCase__functionName" as the
- // program name is acting as the class name.
- if (QTestLog::logMode() == QTestLog::Plain ||
- d->testCaseName.isEmpty()) {
+ if (d->testCaseName.isEmpty()) {
QTestResult::setCurrentTestFunction
(d->intern(name).constData());
} else {
- QString fullName = d->testCaseName + QLatin1String("__") + name;
+ QString fullName = d->testCaseName + QLatin1String("::") + name;
QTestResult::setCurrentTestFunction
(d->intern(fullName).constData());
}
@@ -342,15 +317,7 @@ void QuickTestResult::startLogging()
Q_D(QuickTestResult);
if (loggingStarted)
return;
- const char *saved = QTestResult::currentTestObjectName();
- if (globalProgramName) {
- QTestResult::setCurrentTestObject(globalProgramName);
- } else {
- QTestResult::setCurrentTestObject
- (d->intern(d->testCaseName).constData());
- }
QTestLog::startLogging();
- QTestResult::setCurrentTestObject(saved);
loggingStarted = true;
}
@@ -366,10 +333,8 @@ void QuickTestResult::stopLogging()
Q_D(QuickTestResult);
if (globalProgramName)
return; // Logging will be stopped by setProgramName(0).
- const char *saved = QTestResult::currentTestObjectName();
QTestResult::setCurrentTestObject(d->intern(d->testCaseName).constData());
QTestLog::stopLogging();
- QTestResult::setCurrentTestObject(saved);
}
void QuickTestResult::initTestTable()
@@ -614,6 +579,7 @@ void QuickTestResult::setProgramName(const char *name)
QTestResult::setCurrentTestObject(0);
}
globalProgramName = name;
+ QTestResult::setCurrentTestObject(globalProgramName);
}
int QuickTestResult::exitCode()
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp b/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp
index 777d964716..27ef5438ef 100644
--- a/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativetextedit.cpp
@@ -553,7 +553,15 @@ bool QDeclarative1TextEditPrivate::determineHorizontalAlignment()
{
Q_Q(QDeclarative1TextEdit);
if (hAlignImplicit && q->isComponentComplete()) {
- bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
+ bool alignToRight;
+ if (text.isEmpty()) {
+ const QString preeditText = control->textCursor().block().layout()->preeditAreaText();
+ alignToRight = preeditText.isEmpty()
+ ? QApplication::keyboardInputDirection() == Qt::RightToLeft
+ : preeditText.isRightToLeft();
+ } else {
+ alignToRight = rightToLeftText;
+ }
return setHAlign(alignToRight ? QDeclarative1TextEdit::AlignRight : QDeclarative1TextEdit::AlignLeft);
}
return false;
@@ -1589,6 +1597,7 @@ void QDeclarative1TextEdit::q_textChanged()
void QDeclarative1TextEdit::moveCursorDelegate()
{
Q_D(QDeclarative1TextEdit);
+ d->determineHorizontalAlignment();
updateMicroFocus();
emit cursorRectangleChanged();
if(!d->cursor)
diff --git a/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp b/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
index 544e35d46d..3a36e6b070 100644
--- a/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
@@ -414,7 +414,11 @@ bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
if (hAlignImplicit) {
// if no explicit alignment has been set, follow the natural layout direction of the text
QString text = control->text();
- bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
+ if (text.isEmpty())
+ text = control->preeditAreaText();
+ bool isRightToLeft = text.isEmpty()
+ ? QApplication::keyboardInputDirection() == Qt::RightToLeft
+ : text.isRightToLeft();
return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
}
return false;
@@ -1059,7 +1063,7 @@ void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
Q_Q(QDeclarative1TextInput);
focused = hasFocus;
q->setCursorVisible(hasFocus && scene && scene->hasFocus());
- if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
+ if(!hasFocus && control->passwordEchoEditing())
control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
if (!hasFocus)
control->deselect();
@@ -1915,6 +1919,7 @@ void QDeclarative1TextInput::cursorPosChanged()
void QDeclarative1TextInput::updateCursorRectangle()
{
Q_D(QDeclarative1TextInput);
+ d->determineHorizontalAlignment();
d->updateHorizontalScroll();
updateRect();//TODO: Only update rect between pos's
updateMicroFocus();
diff --git a/src/qtquick1/util/qdeclarativeview.h b/src/qtquick1/util/qdeclarativeview.h
index 96cb4ed2f6..4249d26980 100644
--- a/src/qtquick1/util/qdeclarativeview.h
+++ b/src/qtquick1/util/qdeclarativeview.h
@@ -47,6 +47,7 @@
#include <QtWidgets/qgraphicssceneevent.h>
#include <QtWidgets/qgraphicsview.h>
#include <QtWidgets/qwidget.h>
+#include <QtDeclarative/qdeclarativedebug.h>
QT_BEGIN_HEADER