aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp5
-rw-r--r--src/quick/handlers/handlers.pri1
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp8
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp168
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p.h16
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p_p.h83
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp58
-rw-r--r--src/quick/handlers/qquickpinchhandler_p.h1
-rw-r--r--src/quick/items/context2d/qquickcanvascontext_p.h3
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp7
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h6
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp6
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h2
-rw-r--r--src/quick/items/qquickdrag.cpp1
-rw-r--r--src/quick/items/qquickdrag_p.h2
-rw-r--r--src/quick/items/qquickgenericshadereffect.cpp4
-rw-r--r--src/quick/items/qquickitem.cpp38
-rw-r--r--src/quick/items/qquickitem_p.h5
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp4
-rw-r--r--src/quick/items/qquicktableview.cpp251
-rw-r--r--src/quick/items/qquicktableview_p_p.h13
-rw-r--r--src/quick/qtquick2.cpp1
-rw-r--r--src/quick/util/qquickglobal.cpp7
24 files changed, 443 insertions, 248 deletions
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
index 2efcdada8b..de7da7f9be 100644
--- a/src/quick/designer/qqmldesignermetaobject.cpp
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -45,7 +45,6 @@
#include <QDebug>
#include <private/qqmlengine_p.h>
-#include <private/qqmlpropertycache_p.h>
QT_BEGIN_NAMESPACE
@@ -137,7 +136,7 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi
//Assign cache to object
if (ddata && ddata->propertyCache) {
cache->setParent(ddata->propertyCache);
- cache->invalidate(engine, this);
+ cache->invalidate(this);
ddata->propertyCache->release();
ddata->propertyCache = cache.data();
ddata->propertyCache->addref();
@@ -162,7 +161,7 @@ void QQmlDesignerMetaObject::createNewDynamicProperty(const QString &name)
//Updating cache
QQmlPropertyCache *oldParent = cache->parent();
- QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(m_context->engine(), this);
+ QQmlEnginePrivate::get(m_context->engine())->cache(this)->invalidate(this);
cache->setParent(oldParent);
QQmlProperty property(myObject(), name, m_context);
diff --git a/src/quick/handlers/handlers.pri b/src/quick/handlers/handlers.pri
index 226cca22cb..fa2f25c793 100644
--- a/src/quick/handlers/handlers.pri
+++ b/src/quick/handlers/handlers.pri
@@ -3,6 +3,7 @@ HEADERS += \
$$PWD/qquickhandlerpoint_p.h \
$$PWD/qquickhoverhandler_p.h \
$$PWD/qquickmultipointhandler_p.h \
+ $$PWD/qquickmultipointhandler_p_p.h \
$$PWD/qquickpinchhandler_p.h \
$$PWD/qquickpointerdevicehandler_p.h \
$$PWD/qquickpointerdevicehandler_p_p.h \
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index e5531369cf..22fe3df4d0 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -103,7 +103,7 @@ bool QQuickDragHandler::targetContainsCentroid()
QPointF QQuickDragHandler::targetCentroidPosition()
{
- QPointF pos = m_centroid.position();
+ QPointF pos = centroid().position();
if (target() != parentItem())
pos = parentItem()->mapToItem(target(), pos);
return pos;
@@ -153,7 +153,7 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
if (active()) {
// Calculate drag delta, taking into account the axis enabled constraint
// i.e. if xAxis is not enabled, then ignore the horizontal component of the actual movement
- QVector2D accumulatedDragDelta = QVector2D(m_centroid.scenePosition() - m_centroid.scenePressPosition());
+ QVector2D accumulatedDragDelta = QVector2D(centroid().scenePosition() - centroid().scenePressPosition());
if (!m_xAxis.enabled())
accumulatedDragDelta.setX(0);
if (!m_yAxis.enabled())
@@ -169,9 +169,9 @@ void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event)
QVector <QQuickEventPoint *> chosenPoints;
if (event->isPressEvent())
- m_pressedInsideTarget = target() && m_currentPoints.count() > 0;
+ m_pressedInsideTarget = target() && currentPoints().count() > 0;
- for (const QQuickHandlerPoint &p : m_currentPoints) {
+ for (const QQuickHandlerPoint &p : currentPoints()) {
if (!allOverThreshold)
break;
QQuickEventPoint *point = event->pointById(p.id());
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index baa68e5e53..5c10ecce75 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qquickmultipointhandler_p.h"
+#include "qquickmultipointhandler_p_p.h"
#include <private/qquickitem_p.h>
#include <QLineF>
#include <QMouseEvent>
@@ -59,14 +60,13 @@ QT_BEGIN_NAMESPACE
of multiple touchpoints.
*/
QQuickMultiPointHandler::QQuickMultiPointHandler(QQuickItem *parent, int minimumPointCount, int maximumPointCount)
- : QQuickPointerDeviceHandler(parent)
- , m_minimumPointCount(minimumPointCount)
- , m_maximumPointCount(maximumPointCount)
+ : QQuickPointerDeviceHandler(*(new QQuickMultiPointHandlerPrivate(minimumPointCount, maximumPointCount)), parent)
{
}
bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
{
+ Q_D(QQuickMultiPointHandler);
if (!QQuickPointerDeviceHandler::wantsPointerEvent(event))
return false;
@@ -83,14 +83,14 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
// handle a specific number of points, so a differing number of points will
// usually result in different behavior. But otherwise if the currentPoints
// are all still there in the event, we're good to go (do not reset
- // m_currentPoints, because we don't want to lose the pressPosition, and do
+ // currentPoints, because we don't want to lose the pressPosition, and do
// not want to reshuffle the order either).
const QVector<QQuickEventPoint *> candidatePoints = eligiblePoints(event);
- if (candidatePoints.count() != m_currentPoints.count()) {
- m_currentPoints.clear();
+ if (candidatePoints.count() != d->currentPoints.count()) {
+ d->currentPoints.clear();
if (active()) {
setActive(false);
- m_centroid.reset();
+ d->centroid.reset();
emit centroidChanged();
}
} else if (hasCurrentPoints(event)) {
@@ -100,57 +100,60 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QQuickPointerEvent *event)
const bool ret = (candidatePoints.size() >= minimumPointCount() && candidatePoints.size() <= maximumPointCount());
if (ret) {
const int c = candidatePoints.count();
- m_currentPoints.resize(c);
+ d->currentPoints.resize(c);
for (int i = 0; i < c; ++i) {
- m_currentPoints[i].reset(candidatePoints[i]);
- m_currentPoints[i].localize(parentItem());
+ d->currentPoints[i].reset(candidatePoints[i]);
+ d->currentPoints[i].localize(parentItem());
}
} else {
- m_currentPoints.clear();
+ d->currentPoints.clear();
}
return ret;
}
void QQuickMultiPointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
+ Q_D(QQuickMultiPointHandler);
QQuickPointerHandler::handlePointerEventImpl(event);
- // event's points can be reordered since the previous event, which is why m_currentPoints
+ // event's points can be reordered since the previous event, which is why currentPoints
// is _not_ a shallow copy of the QQuickPointerTouchEvent::m_touchPoints vector.
- // So we have to update our m_currentPoints instances based on the given event.
- for (QQuickHandlerPoint &p : m_currentPoints) {
+ // So we have to update our currentPoints instances based on the given event.
+ for (QQuickHandlerPoint &p : d->currentPoints) {
const QQuickEventPoint *ep = event->pointById(p.id());
if (ep)
p.reset(ep);
}
- QPointF sceneGrabPos = m_centroid.sceneGrabPosition();
- m_centroid.reset(m_currentPoints);
- m_centroid.m_sceneGrabPosition = sceneGrabPos; // preserve as it was
+ QPointF sceneGrabPos = d->centroid.sceneGrabPosition();
+ d->centroid.reset(d->currentPoints);
+ d->centroid.m_sceneGrabPosition = sceneGrabPos; // preserve as it was
emit centroidChanged();
}
void QQuickMultiPointHandler::onActiveChanged()
{
+ Q_D(QQuickMultiPointHandler);
if (active()) {
- m_centroid.m_sceneGrabPosition = m_centroid.m_scenePosition;
+ d->centroid.m_sceneGrabPosition = d->centroid.m_scenePosition;
} else {
- // Don't call m_centroid.reset() here, because in a QML onActiveChanged
+ // Don't call centroid.reset() here, because in a QML onActiveChanged
// callback, we'd like to see what the position _was_, what the velocity _was_, etc.
// (having them undefined is not useful)
// But pressedButtons and pressedModifiers are meant to be more real-time than those
// (which seems a bit inconsistent, from one side).
- m_centroid.m_pressedButtons = Qt::NoButton;
- m_centroid.m_pressedModifiers = Qt::NoModifier;
+ d->centroid.m_pressedButtons = Qt::NoButton;
+ d->centroid.m_pressedModifiers = Qt::NoModifier;
}
}
void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *)
{
+ Q_D(QQuickMultiPointHandler);
// If another handler or item takes over this set of points, assume it has
// decided that it's the better fit for them. Don't immediately re-grab
// at the next opportunity. This should help to avoid grab cycles
// (e.g. between DragHandler and PinchHandler).
if (transition == QQuickEventPoint::UngrabExclusive || transition == QQuickEventPoint::CancelGrabExclusive)
- m_currentPoints.clear();
+ d->currentPoints.clear();
}
QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointerEvent *event)
@@ -190,14 +193,21 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe
The default value is 2.
*/
+int QQuickMultiPointHandler::minimumPointCount() const
+{
+ Q_D(const QQuickMultiPointHandler);
+ return d->minimumPointCount;
+}
+
void QQuickMultiPointHandler::setMinimumPointCount(int c)
{
- if (m_minimumPointCount == c)
+ Q_D(QQuickMultiPointHandler);
+ if (d->minimumPointCount == c)
return;
- m_minimumPointCount = c;
+ d->minimumPointCount = c;
emit minimumPointCountChanged();
- if (m_maximumPointCount < 0)
+ if (d->maximumPointCount < 0)
emit maximumPointCountChanged();
}
@@ -216,22 +226,61 @@ void QQuickMultiPointHandler::setMinimumPointCount(int c)
The default value is the same as \l minimumPointCount.
*/
+int QQuickMultiPointHandler::maximumPointCount() const
+{
+ Q_D(const QQuickMultiPointHandler);
+ return d->maximumPointCount >= 0 ? d->maximumPointCount : d->minimumPointCount;
+}
+
void QQuickMultiPointHandler::setMaximumPointCount(int maximumPointCount)
{
- if (m_maximumPointCount == maximumPointCount)
+ Q_D(QQuickMultiPointHandler);
+ if (d->maximumPointCount == maximumPointCount)
return;
- m_maximumPointCount = maximumPointCount;
+ d->maximumPointCount = maximumPointCount;
emit maximumPointCountChanged();
}
+/*!
+ \readonly
+ \qmlproperty QtQuick::HandlerPoint QtQuick::MultiPointHandler::centroid
+
+ A point exactly in the middle of the currently-pressed touch points.
+ If only one point is pressed, it's the same as that point.
+ A handler that has a \l target will normally transform it relative to this point.
+*/
+const QQuickHandlerPoint &QQuickMultiPointHandler::centroid() const
+{
+ Q_D(const QQuickMultiPointHandler);
+ return d->centroid;
+}
+
+/*!
+ Returns a modifiable reference to the point that will be returned by the
+ \l centroid property. If you modify it, you are responsible to emit
+ \l centroidChanged.
+*/
+QQuickHandlerPoint &QQuickMultiPointHandler::mutableCentroid()
+{
+ Q_D(QQuickMultiPointHandler);
+ return d->centroid;
+}
+
+QVector<QQuickHandlerPoint> &QQuickMultiPointHandler::currentPoints()
+{
+ Q_D(QQuickMultiPointHandler);
+ return d->currentPoints;
+}
+
bool QQuickMultiPointHandler::hasCurrentPoints(QQuickPointerEvent *event)
{
- if (event->pointCount() < m_currentPoints.size() || m_currentPoints.size() == 0)
+ Q_D(const QQuickMultiPointHandler);
+ if (event->pointCount() < d->currentPoints.size() || d->currentPoints.size() == 0)
return false;
// TODO optimize: either ensure the points are sorted,
// or use std::equal with a predicate
- for (const QQuickHandlerPoint &p : qAsConst(m_currentPoints)) {
+ for (const QQuickHandlerPoint &p : qAsConst(d->currentPoints)) {
const QQuickEventPoint *ep = event->pointById(p.id());
if (!ep)
return false;
@@ -243,30 +292,33 @@ bool QQuickMultiPointHandler::hasCurrentPoints(QQuickPointerEvent *event)
qreal QQuickMultiPointHandler::averageTouchPointDistance(const QPointF &ref)
{
+ Q_D(const QQuickMultiPointHandler);
qreal ret = 0;
- if (Q_UNLIKELY(m_currentPoints.size() == 0))
+ if (Q_UNLIKELY(d->currentPoints.size() == 0))
return ret;
- for (const QQuickHandlerPoint &p : m_currentPoints)
+ for (const QQuickHandlerPoint &p : d->currentPoints)
ret += QVector2D(p.scenePosition() - ref).length();
- return ret / m_currentPoints.size();
+ return ret / d->currentPoints.size();
}
qreal QQuickMultiPointHandler::averageStartingDistance(const QPointF &ref)
{
+ Q_D(const QQuickMultiPointHandler);
// TODO cache it in setActive()?
qreal ret = 0;
- if (Q_UNLIKELY(m_currentPoints.size() == 0))
+ if (Q_UNLIKELY(d->currentPoints.size() == 0))
return ret;
- for (const QQuickHandlerPoint &p : m_currentPoints)
+ for (const QQuickHandlerPoint &p : d->currentPoints)
ret += QVector2D(p.sceneGrabPosition() - ref).length();
- return ret / m_currentPoints.size();
+ return ret / d->currentPoints.size();
}
QVector<QQuickMultiPointHandler::PointData> QQuickMultiPointHandler::angles(const QPointF &ref) const
{
+ Q_D(const QQuickMultiPointHandler);
QVector<PointData> angles;
- angles.reserve(m_currentPoints.count());
- for (const QQuickHandlerPoint &p : m_currentPoints) {
+ angles.reserve(d->currentPoints.count());
+ for (const QQuickHandlerPoint &p : d->currentPoints) {
qreal angle = QLineF(ref, p.scenePosition()).angle();
angles.append(PointData(p.id(), -angle)); // convert to clockwise, to be consistent with QQuickItem::rotation
}
@@ -331,17 +383,41 @@ bool QQuickMultiPointHandler::grabPoints(QVector<QQuickEventPoint *> points)
void QQuickMultiPointHandler::moveTarget(QPointF pos)
{
- target()->setPosition(pos);
- m_centroid.m_position = target()->mapFromScene(m_centroid.m_scenePosition);
+ Q_D(QQuickMultiPointHandler);
+ if (QQuickItem *t = target()) {
+ d->xMetaProperty().write(t, pos.x());
+ d->yMetaProperty().write(t, pos.y());
+ d->centroid.m_position = t->mapFromScene(d->centroid.m_scenePosition);
+ } else {
+ qWarning() << "moveTarget: target is null";
+ }
}
-/*!
- \readonly
- \qmlproperty QtQuick::HandlerPoint QtQuick::MultiPointHandler::centroid
+QQuickMultiPointHandlerPrivate::QQuickMultiPointHandlerPrivate(int minPointCount, int maxPointCount)
+ : QQuickPointerDeviceHandlerPrivate()
+ , minimumPointCount(minPointCount)
+ , maximumPointCount(maxPointCount)
+{
+}
- A point exactly in the middle of the currently-pressed touch points.
- If only one point is pressed, it's the same as that point.
- A handler that has a \l target will normally transform it relative to this point.
-*/
+QMetaProperty &QQuickMultiPointHandlerPrivate::xMetaProperty() const
+{
+ Q_Q(const QQuickMultiPointHandler);
+ if (!xProperty.isValid() && q->target()) {
+ const QMetaObject *targetMeta = q->target()->metaObject();
+ xProperty = targetMeta->property(targetMeta->indexOfProperty("x"));
+ }
+ return xProperty;
+}
+
+QMetaProperty &QQuickMultiPointHandlerPrivate::yMetaProperty() const
+{
+ Q_Q(const QQuickMultiPointHandler);
+ if (!yProperty.isValid() && q->target()) {
+ const QMetaObject *targetMeta = q->target()->metaObject();
+ yProperty = targetMeta->property(targetMeta->indexOfProperty("y"));
+ }
+ return yProperty;
+}
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h
index 06f170154b..eeb4b13b83 100644
--- a/src/quick/handlers/qquickmultipointhandler_p.h
+++ b/src/quick/handlers/qquickmultipointhandler_p.h
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+class QQuickMultiPointHandlerPrivate;
+
class Q_QUICK_PRIVATE_EXPORT QQuickMultiPointHandler : public QQuickPointerDeviceHandler
{
Q_OBJECT
@@ -68,13 +70,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMultiPointHandler : public QQuickPointerDevic
public:
explicit QQuickMultiPointHandler(QQuickItem *parent = nullptr, int minimumPointCount = 2, int maximumPointCount = -1);
- int minimumPointCount() const { return m_minimumPointCount; }
+ int minimumPointCount() const;
void setMinimumPointCount(int c);
- int maximumPointCount() const { return m_maximumPointCount >= 0 ? m_maximumPointCount : m_minimumPointCount; }
+ int maximumPointCount() const;
void setMaximumPointCount(int maximumPointCount);
- QQuickHandlerPoint centroid() const { return m_centroid; }
+ const QQuickHandlerPoint &centroid() const;
signals:
void minimumPointCountChanged();
@@ -94,6 +96,8 @@ protected:
void handlePointerEventImpl(QQuickPointerEvent *event) override;
void onActiveChanged() override;
void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point) override;
+ QVector<QQuickHandlerPoint> &currentPoints();
+ QQuickHandlerPoint &mutableCentroid();
bool hasCurrentPoints(QQuickPointerEvent *event);
QVector<QQuickEventPoint *> eligiblePoints(QQuickPointerEvent *event);
qreal averageTouchPointDistance(const QPointF &ref);
@@ -106,11 +110,7 @@ protected:
bool grabPoints(QVector<QQuickEventPoint *> points);
void moveTarget(QPointF pos);
-protected:
- QVector<QQuickHandlerPoint> m_currentPoints;
- QQuickHandlerPoint m_centroid;
- int m_minimumPointCount;
- int m_maximumPointCount;
+ Q_DECLARE_PRIVATE(QQuickMultiPointHandler)
};
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickmultipointhandler_p_p.h b/src/quick/handlers/qquickmultipointhandler_p_p.h
new file mode 100644
index 0000000000..406e4a1fdf
--- /dev/null
+++ b/src/quick/handlers/qquickmultipointhandler_p_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOINTERMULTIHANDLER_P_H
+#define QQUICKPOINTERMULTIHANDLER_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 "qquickhandlerpoint_p.h"
+#include "qquickpointerdevicehandler_p_p.h"
+#include "qquickmultipointhandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QQuickMultiPointHandlerPrivate : public QQuickPointerDeviceHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickMultiPointHandler)
+
+public:
+ static QQuickMultiPointHandlerPrivate* get(QQuickMultiPointHandler *q) { return q->d_func(); }
+ static const QQuickMultiPointHandlerPrivate* get(const QQuickMultiPointHandler *q) { return q->d_func(); }
+
+ QQuickMultiPointHandlerPrivate(int minPointCount, int maxPointCount);
+
+ QMetaProperty &xMetaProperty() const;
+ QMetaProperty &yMetaProperty() const;
+
+ QVector<QQuickHandlerPoint> currentPoints;
+ QQuickHandlerPoint centroid;
+ int minimumPointCount;
+ int maximumPointCount;
+ mutable QMetaProperty xProperty;
+ mutable QMetaProperty yProperty;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOINTERMULTIHANDLER_P_H
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 9ae2116d39..4025cd7fbf 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -267,20 +267,14 @@ void QQuickPinchHandler::onActiveChanged()
{
QQuickMultiPointHandler::onActiveChanged();
if (active()) {
- m_startMatrix = QMatrix4x4();
- m_startAngles = angles(m_centroid.sceneGrabPosition());
- m_startDistance = averageTouchPointDistance(m_centroid.sceneGrabPosition());
+ m_startAngles = angles(centroid().sceneGrabPosition());
+ m_startDistance = averageTouchPointDistance(centroid().sceneGrabPosition());
m_activeRotation = 0;
m_activeTranslation = QVector2D();
if (const QQuickItem *t = target()) {
m_startScale = t->scale(); // TODO incompatible with independent x/y scaling
m_startRotation = t->rotation();
- QVector3D xformOrigin(t->transformOriginPoint());
- m_startMatrix.translate(float(t->x()), float(t->y()));
- m_startMatrix.translate(xformOrigin);
- m_startMatrix.scale(float(m_startScale));
- m_startMatrix.rotate(float(m_startRotation), 0, 0, -1);
- m_startMatrix.translate(-xformOrigin);
+ m_startPos = t->position();
} else {
m_startScale = m_accumulatedScale;
m_startRotation = 0;
@@ -294,7 +288,7 @@ void QQuickPinchHandler::onActiveChanged()
void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) {
- for (const QQuickHandlerPoint &p : m_currentPoints)
+ for (const QQuickHandlerPoint &p : currentPoints())
qCDebug(lcPinchHandler) << hex << p.id() << p.sceneGrabPosition() << "->" << p.scenePosition();
}
QQuickMultiPointHandler::handlePointerEventImpl(event);
@@ -302,13 +296,13 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
qreal dist = 0;
#if QT_CONFIG(gestures)
if (const auto gesture = event->asPointerNativeGestureEvent()) {
- m_centroid.reset(event->point(0));
+ mutableCentroid().reset(event->point(0));
switch (gesture->type()) {
case Qt::EndNativeGesture:
m_activeScale = 1;
m_activeRotation = 0;
m_activeTranslation = QVector2D();
- m_centroid.reset();
+ mutableCentroid().reset();
setActive(false);
emit updated();
return;
@@ -333,7 +327,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
const bool containsReleasedPoints = event->isReleaseEvent();
QVector<QQuickEventPoint *> chosenPoints;
- for (const QQuickHandlerPoint &p : m_currentPoints) {
+ for (const QQuickHandlerPoint &p : currentPoints()) {
QQuickEventPoint *ep = event->pointById(p.id());
chosenPoints << ep;
}
@@ -341,8 +335,8 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
// Verify that at least one of the points has moved beyond threshold needed to activate the handler
int numberOfPointsDraggedOverThreshold = 0;
QVector2D accumulatedDrag;
- const QVector2D currentCentroid(m_centroid.scenePosition());
- const QVector2D pressCentroid(m_centroid.scenePressPosition());
+ const QVector2D currentCentroid(centroid().scenePosition());
+ const QVector2D pressCentroid(centroid().scenePressPosition());
QStyleHints *styleHints = QGuiApplication::styleHints();
const int dragThreshold = styleHints->startDragDistance();
@@ -410,9 +404,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
}
const bool requiredNumberOfPointsDraggedOverThreshold = numberOfPointsDraggedOverThreshold >= minimumPointCount() && numberOfPointsDraggedOverThreshold <= maximumPointCount();
- accumulatedMovementMagnitude /= m_currentPoints.count();
+ accumulatedMovementMagnitude /= currentPoints().count();
- QVector2D avgDrag = accumulatedDrag / m_currentPoints.count();
+ QVector2D avgDrag = accumulatedDrag / currentPoints().count();
if (!xAxis()->enabled())
avgDrag.setX(0);
if (!yAxis()->enabled())
@@ -445,12 +439,12 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
// avoid mapping the minima and maxima, as they might have unmappable values
// such as -inf/+inf. Because of this we perform the bounding to min/max in local coords.
// 1. scale
- dist = averageTouchPointDistance(m_centroid.scenePosition());
+ dist = averageTouchPointDistance(centroid().scenePosition());
m_activeScale = dist / m_startDistance;
m_activeScale = qBound(m_minimumScale/m_startScale, m_activeScale, m_maximumScale/m_startScale);
// 2. rotate
- QVector<PointData> newAngles = angles(m_centroid.scenePosition());
+ QVector<PointData> newAngles = angles(centroid().scenePosition());
const qreal angleDelta = averageAngleDelta(m_startAngles, newAngles);
m_activeRotation += angleDelta;
m_startAngles = std::move(newAngles);
@@ -465,25 +459,15 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
m_accumulatedScale = m_startScale * m_activeScale;
if (target() && target()->parentItem()) {
- const QPointF centroidParentPos = target()->parentItem()->mapFromScene(m_centroid.scenePosition());
+ const QPointF centroidParentPos = target()->parentItem()->mapFromScene(centroid().scenePosition());
// 3. Drag/translate
- const QPointF centroidStartParentPos = target()->parentItem()->mapFromScene(m_centroid.sceneGrabPosition());
+ const QPointF centroidStartParentPos = target()->parentItem()->mapFromScene(centroid().sceneGrabPosition());
m_activeTranslation = QVector2D(centroidParentPos - centroidStartParentPos);
// apply rotation + scaling around the centroid - then apply translation.
- QMatrix4x4 mat;
-
- const QVector3D centroidParentVector(centroidParentPos);
- mat.translate(centroidParentVector);
- mat.rotate(float(m_activeRotation), 0, 0, 1);
- mat.scale(float(m_activeScale));
- mat.translate(-centroidParentVector);
- mat.translate(QVector3D(m_activeTranslation));
-
- mat = mat * m_startMatrix;
-
- QPointF xformOriginPoint = target()->transformOriginPoint();
- QPointF pos = mat * xformOriginPoint;
- pos -= xformOriginPoint;
+ QPointF pos = QQuickItemPrivate::get(target())->adjustedPosForTransform(centroidParentPos,
+ m_startPos, m_activeTranslation,
+ m_startScale, m_activeScale,
+ m_startRotation, m_activeRotation);
if (xAxis()->enabled())
pos.setX(qBound(xAxis()->minimum(), pos.x(), xAxis()->maximum()));
@@ -498,10 +482,10 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
target()->setRotation(rotation);
target()->setScale(m_accumulatedScale);
} else {
- m_activeTranslation = QVector2D(m_centroid.scenePosition() - m_centroid.scenePressPosition());
+ m_activeTranslation = QVector2D(centroid().scenePosition() - centroid().scenePressPosition());
}
- qCDebug(lcPinchHandler) << "centroid" << m_centroid.scenePressPosition() << "->" << m_centroid.scenePosition()
+ qCDebug(lcPinchHandler) << "centroid" << centroid().scenePressPosition() << "->" << centroid().scenePosition()
<< ", distance" << m_startDistance << "->" << dist
<< ", startScale" << m_startScale << "->" << m_accumulatedScale
<< ", activeRotation" << m_activeRotation
diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h
index 766d57f892..cea794f0c8 100644
--- a/src/quick/handlers/qquickpinchhandler_p.h
+++ b/src/quick/handlers/qquickpinchhandler_p.h
@@ -158,7 +158,6 @@ private:
qreal m_accumulatedStartCentroidDistance = 0;
QVector<PointData> m_startAngles;
QQuickMatrix4x4 m_transform;
- QMatrix4x4 m_startMatrix;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h
index 95100d2912..3872a2ac74 100644
--- a/src/quick/items/context2d/qquickcanvascontext_p.h
+++ b/src/quick/items/context2d/qquickcanvascontext_p.h
@@ -56,7 +56,7 @@
QT_REQUIRE_CONFIG(quick_canvas);
#include <QtQuick/qquickitem.h>
-#include <private/qv8engine_p.h>
+#include <QtQml/private/qv4value_p.h>
QT_BEGIN_NAMESPACE
@@ -80,6 +80,7 @@ public:
virtual void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing);
virtual void flush();
+ virtual QV4::ExecutionEngine *v4Engine() const = 0;
virtual void setV4Engine(QV4::ExecutionEngine *engine) = 0;
virtual QV4::ReturnedValue v4value() const = 0;
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 14443a2f2f..188e74cd89 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -378,13 +378,10 @@ void QQuickCanvasItem::setContextType(const QString &contextType)
this property will contain the current drawing context, otherwise null.
*/
-QQmlV4Handle QQuickCanvasItem::context() const
+QJSValue QQuickCanvasItem::context() const
{
Q_D(const QQuickCanvasItem);
- if (d->context)
- return QQmlV4Handle(d->context->v4value());
-
- return QQmlV4Handle(QV4::Encode::null());
+ return d->context ? QJSValue(d->context->v4Engine(), d->context->v4value()) : QJSValue();
}
/*!
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index 7dc981a6eb..cd2977429b 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -56,9 +56,9 @@
QT_REQUIRE_CONFIG(quick_canvas);
#include <QtQuick/qquickitem.h>
-#include <private/qv8engine_p.h>
#include <private/qqmlrefcount_p.h>
#include <QtCore/QThread>
+#include <QtCore/qmutex.h>
#include <QtGui/QImage>
QT_BEGIN_NAMESPACE
@@ -93,7 +93,7 @@ class QQuickCanvasItem : public QQuickItem
Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
Q_PROPERTY(QString contextType READ contextType WRITE setContextType NOTIFY contextTypeChanged)
- Q_PROPERTY(QQmlV4Handle context READ context NOTIFY contextChanged)
+ Q_PROPERTY(QJSValue context READ context NOTIFY contextChanged)
Q_PROPERTY(QSizeF canvasSize READ canvasSize WRITE setCanvasSize NOTIFY canvasSizeChanged)
Q_PROPERTY(QSize tileSize READ tileSize WRITE setTileSize NOTIFY tileSizeChanged)
Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
@@ -122,7 +122,7 @@ public:
QString contextType() const;
void setContextType(const QString &contextType);
- QQmlV4Handle context() const;
+ QJSValue context() const;
QSizeF canvasSize() const;
void setCanvasSize(const QSizeF &);
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 546f3011ec..58bc12a221 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -56,7 +56,6 @@
#include <private/qquickimage_p_p.h>
#include <qqmlinfo.h>
-#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <private/qv4domerrors_p.h>
@@ -4552,6 +4551,11 @@ void QQuickContext2D::reset()
m_buffer->clearRect(QRectF(0, 0, m_canvas->width(), m_canvas->height()));
}
+QV4::ExecutionEngine *QQuickContext2D::v4Engine() const
+{
+ return m_v4engine;
+}
+
void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine)
{
if (m_v4engine != engine) {
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 1ece6796f3..b5626dec0c 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -65,7 +65,6 @@ QT_REQUIRE_CONFIG(quick_canvas);
#include <QtCore/qstring.h>
#include <QtCore/qstack.h>
#include <QtCore/qqueue.h>
-#include <private/qv8engine_p.h>
#include <QtCore/QWaitCondition>
#include <private/qv4value_p.h>
@@ -199,6 +198,7 @@ public:
QImage toImage(const QRectF& bounds) override;
QV4::ReturnedValue v4value() const override;
+ QV4::ExecutionEngine *v4Engine() const override;
void setV4Engine(QV4::ExecutionEngine *eng) override;
QQuickCanvasItem* canvas() const { return m_canvas; }
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index f60f3c1ccf..74a00435e7 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -45,7 +45,6 @@
#include <QtQuick/private/qquickevents_p_p.h>
#include <private/qquickitemchangelistener_p.h>
#include <private/qquickpixmapcache_p.h>
-#include <private/qv8engine_p.h>
#include <private/qv4scopedvalue_p.h>
#include <QtCore/qmimedata.h>
#include <QtQml/qqmlinfo.h>
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 6bfbae74c9..81f3fb5e5c 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -53,7 +53,7 @@
#include <QtQuick/qquickitem.h>
-#include <private/qv8engine_p.h>
+#include <private/qintrusivelist_p.h>
#include <private/qqmlguard_p.h>
#include <QtCore/qmimedata.h>
diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp
index 248c2b6ec3..3e7eda28eb 100644
--- a/src/quick/items/qquickgenericshadereffect.cpp
+++ b/src/quick/items/qquickgenericshadereffect.cpp
@@ -123,8 +123,8 @@ void QQuickGenericShaderEffect::setBlending(bool enable)
QVariant QQuickGenericShaderEffect::mesh() const
{
- return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
- : qVariantFromValue(m_meshResolution);
+ return m_mesh ? QVariant::fromValue(static_cast<QObject *>(m_mesh))
+ : QVariant::fromValue(m_meshResolution);
}
void QQuickGenericShaderEffect::setMesh(const QVariant &mesh)
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index ec6bf5a1b8..e114404524 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -5122,6 +5122,40 @@ void QQuickItemPrivate::transformChanged()
#endif
}
+QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF &centroidParentPos,
+ const QPointF &startPos,
+ const QVector2D &activeTranslation, //[0,0] means no additional translation from startPos
+ qreal startScale,
+ qreal activeScale, // 1.0 means no additional scale from startScale
+ qreal startRotation,
+ qreal activeRotation) // 0.0 means no additional rotation from startRotation
+{
+ Q_Q(QQuickItem);
+ QVector3D xformOrigin(q->transformOriginPoint());
+ QMatrix4x4 startMatrix;
+ startMatrix.translate(float(startPos.x()), float(startPos.y()));
+ startMatrix.translate(xformOrigin);
+ startMatrix.scale(float(startScale));
+ startMatrix.rotate(float(startRotation), 0, 0, -1);
+ startMatrix.translate(-xformOrigin);
+
+ const QVector3D centroidParentVector(centroidParentPos);
+ QMatrix4x4 mat;
+ mat.translate(centroidParentVector);
+ mat.rotate(float(activeRotation), 0, 0, 1);
+ mat.scale(float(activeScale));
+ mat.translate(-centroidParentVector);
+ mat.translate(QVector3D(activeTranslation));
+
+ mat = mat * startMatrix;
+
+ QPointF xformOriginPoint = q->transformOriginPoint();
+ QPointF pos = mat * xformOriginPoint;
+ pos -= xformOriginPoint;
+
+ return pos;
+}
+
bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post)
{
if (!extra.isAllocated() || !extra->keyHandler)
@@ -8359,7 +8393,7 @@ void QQuickItemLayer::activateEffect()
m_effect->stackAfter(m_effectSource);
}
m_effect->setVisible(m_item->isVisible());
- m_effect->setProperty(m_name, qVariantFromValue<QObject *>(m_effectSource));
+ m_effect->setProperty(m_name, QVariant::fromValue<QObject *>(m_effectSource));
QQuickItemPrivate::get(m_effect)->setTransparentForPositioner(true);
m_effectComponent->completeCreate();
}
@@ -8656,7 +8690,7 @@ void QQuickItemLayer::setName(const QByteArray &name) {
return;
if (m_effect) {
m_effect->setProperty(m_name, QVariant());
- m_effect->setProperty(name, qVariantFromValue<QObject *>(m_effectSource));
+ m_effect->setProperty(name, QVariant::fromValue<QObject *>(m_effectSource));
}
m_name = name;
emit nameChanged(name);
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 771228914b..847fd90230 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -591,6 +591,11 @@ public:
QPointF computeTransformOrigin() const;
virtual void transformChanged();
+ QPointF adjustedPosForTransform(const QPointF &centroid,
+ const QPointF &startPos, const QVector2D &activeTranslatation,
+ qreal startScale, qreal activeScale,
+ qreal startRotation, qreal activeRotation);
+
void deliverKeyEvent(QKeyEvent *);
bool filterKeyEvent(QKeyEvent *, bool post);
#if QT_CONFIG(im)
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index ddd438e56d..cd5cca5ac9 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -113,7 +113,6 @@
#include "qquickdrag_p.h"
#include "qquickdroparea_p.h"
#include "qquickmultipointtoucharea_p.h"
-#include <private/qqmlmetatype_p.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
#include "handlers/qquickdraghandler_p.h"
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index 3aa00340b2..bc1f787b81 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -710,8 +710,8 @@ void QQuickOpenGLShaderEffect::setBlending(bool enable)
QVariant QQuickOpenGLShaderEffect::mesh() const
{
- return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
- : qVariantFromValue(m_meshResolution);
+ return m_mesh ? QVariant::fromValue(static_cast<QObject *>(m_mesh))
+ : QVariant::fromValue(m_meshResolution);
}
void QQuickOpenGLShaderEffect::setMesh(const QVariant &mesh)
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index ac3397d2a9..1dca5bea4a 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -53,11 +53,10 @@
/*!
\qmltype TableView
- \instantiates QQuickTableView
\inqmlmodule QtQuick
\ingroup qtquick-views
\inherits Flickable
- \brief Provides a table view of items provided by the model.
+ \brief Provides a table view of items to display data from a model.
A TableView has a \l model that defines the data to be displayed, and a
\l delegate that defines how the data should be displayed.
@@ -72,8 +71,8 @@
A TableView displays data from models created from built-in QML types
such as ListModel and XmlListModel, which populates the first column only
- in a TableView. To create models with multiple columns, create a model in
- C++ that inherits QAbstractItemModel, and expose it to QML.
+ in a TableView. To create models with multiple columns, either use
+ \l TableModel or a C++ model that inherits QAbstractItemModel.
\section1 Example Usage
@@ -90,7 +89,7 @@
TableView recycles delegate items by default, instead of instantiating from
the \l delegate whenever new rows and columns are flicked into view. This
- can give a huge performance boost, depending on the complexity of the
+ approach gives a huge performance boost, depending on the complexity of the
delegate.
When an item is flicked out, it moves to the \e{reuse pool}, which is an
@@ -124,8 +123,8 @@
\section1 Row heights and column widths
When a new column is flicked into view, TableView will determine its width
- by calling the \l columnWidthProvider function. TableView itself will never
- store row height or column width, as it's designed to support large models
+ by calling the \l columnWidthProvider function. TableView does not store
+ row height or column width, as it's designed to support large models
containing any number of rows and columns. Instead, it will ask the
application whenever it needs to know.
@@ -139,9 +138,9 @@
\note The calculated width of a column is discarded when it is flicked out
of the viewport, and is recalculated if the column is flicked back in. The
calculation is always based on the items that are visible when the column
- is flicked in. This means that it can end up different each time, depending
- on which row you're at when the column enters. You should therefore have the
- same \c implicitWidth for all items in a column, or set
+ is flicked in. This means that column width can be different each time,
+ depending on which row you're at when the column enters. You should
+ therefore have the same \c implicitWidth for all items in a column, or set
\l columnWidthProvider. The same logic applies for the row height
calculation.
@@ -150,10 +149,11 @@
must call \l forceLayout. This informs TableView that it needs to use the
provider functions again to recalculate and update the layout.
- Since Qt 5.13, if you want to hide a specific column, you can return \c 0 from the
- \l columnWidthProvider for that column. Likewise, you can return 0 from the
- \l rowHeightProvider to hide a row. If you return a negative number, TableView
- will fall back to calculate the size based on the delegate items.
+ Since Qt 5.13, if you want to hide a specific column, you can return \c 0
+ from the \l columnWidthProvider for that column. Likewise, you can return 0
+ from the \l rowHeightProvider to hide a row. If you return a negative
+ number, TableView will fall back to calculate the size based on the delegate
+ items.
\note The size of a row or column should be a whole number to avoid
sub-pixel alignment of items.
@@ -167,11 +167,11 @@
\section1 Overlays and underlays
- Tableview inherits \l Flickable. And when new items are instantiated from the
- delegate, it will parent them to the \l{Flickable::}{contentItem}
- with a \c z value equal to \c 1. You can add your own items inside the
- Tableview, as child items of the Flickable. By controlling their \c z
- value, you can make them be on top of or underneath the table items.
+ All new items that are instantiated from the delegate are parented to the
+ \l{Flickable::}{contentItem} with the \c z value, \c 1. You can add your
+ own items inside the Tableview, as child items of the Flickable. By
+ controlling their \c z value, you can make them be on top of or
+ underneath the table items.
Here is an example that shows how to add some text on top of the table, that
moves together with the table as you flick:
@@ -181,6 +181,7 @@
/*!
\qmlproperty int QtQuick::TableView::rows
+ \readonly
This property holds the number of rows in the table. This is
equal to the number of rows in the model.
@@ -190,10 +191,11 @@
/*!
\qmlproperty int QtQuick::TableView::columns
+ \readonly
This property holds the number of columns in the table. This is
equal to the number of columns in the model. If the model is
- a list, columns will be 1.
+ a list, columns will be \c 1.
This property is read only.
*/
@@ -203,7 +205,7 @@
This property holds the spacing between the rows.
- The default value is 0.
+ The default value is \c 0.
*/
/*!
@@ -211,20 +213,20 @@
This property holds the spacing between the columns.
- The default value is 0.
+ The default value is \c 0.
*/
/*!
\qmlproperty var QtQuick::TableView::rowHeightProvider
This property can hold a function that returns the row height for each row
- in the model. When assigned, it will be called whenever TableView needs to
- know the height of a specific row. The function takes one argument, \c row,
- for which the TableView needs to know the height.
+ in the model. It is called whenever TableView needs to know the height of
+ a specific row. The function takes one argument, \c row, for which the
+ TableView needs to know the height.
- Since Qt 5.13, if you want to hide a specific row, you can return \c 0 height for
- that row. If you return a negative number, TableView will fall back to
- calculate the height based on the delegate items.
+ Since Qt 5.13, if you want to hide a specific row, you can return \c 0
+ height for that row. If you return a negative number, TableView calculates
+ the height based on the delegate items.
\sa columnWidthProvider, {Row heights and column widths}
*/
@@ -233,13 +235,13 @@
\qmlproperty var QtQuick::TableView::columnWidthProvider
This property can hold a function that returns the column width for each
- column in the model. When assigned, it is called whenever TableView needs
- to know the width of a specific column. The function takes one argument,
- \c column, for which the TableView needs to know the width.
+ column in the model. It is called whenever TableView needs to know the
+ width of a specific column. The function takes one argument, \c column,
+ for which the TableView needs to know the width.
- Since Qt 5.13, if you want to hide a specific column, you can return \c 0 width for
- that column. If you return a negative number, TableView will fall back to
- calculate the width based on the delegate items.
+ Since Qt 5.13, if you want to hide a specific column, you can return \c 0
+ width for that column. If you return a negative number, TableView
+ calculates the width based on the delegate items.
\sa rowHeightProvider, {Row heights and column widths}
*/
@@ -249,9 +251,9 @@
This property holds the model that provides data for the table.
The model provides the set of data that is used to create the items
- in the view. Models can be created directly in QML using \l ListModel,
- \l XmlListModel or \l ObjectModel, or provided by a custom C++ model
- class. If it is a C++ model, it must be a subclass of \l QAbstractItemModel
+ in the view. Models can be created directly in QML using \l TableModel,
+ \l ListModel, \l XmlListModel, or \l ObjectModel, or provided by a custom
+ C++ model class. The C++ model must be a subclass of \l QAbstractItemModel
or a simple list.
\sa {qml-data-models}{Data Models}
@@ -265,10 +267,9 @@
applies to \c row and \c column. Properties of the model are also available
depending upon the type of \l {qml-data-models}{Data Model}.
- A delegate should specify its size using \l [QML]{Item::implicitWidth}{implicitWidth} and
- \l [QML]{Item::implicitHeight}{implicitHeight}.
- The TableView lays out the items based on that information. Explicit width or
- height settings are ignored and overwritten.
+ A delegate should specify its size using \l{Item::}{implicitWidth} and
+ \l {Item::}{implicitHeight}. The TableView lays out the items based on that
+ information. Explicit width or height settings are ignored and overwritten.
\note Delegates are instantiated as needed and may be destroyed at any time.
They are also reused if the \l reuseItems property is set to \c true. You
@@ -290,37 +291,39 @@
/*!
\qmlproperty real QtQuick::TableView::contentWidth
- This property holds the width of the \l view, which is also
- the width of the table (including margins). As a TableView cannot
- always know the exact width of the table without loading all columns
- in the model, the \c contentWidth is usually an estimated width based on
- the columns it has seen so far. This estimate is recalculated whenever
- new columns are flicked into view, which means that the content width
- can change dynamically.
+ This property holds the table width required to accommodate the number of
+ columns in the model. This is usually not the same as the \c width of the
+ \l view, which means that the table's width could be larger or smaller than
+ the viewport width. As a TableView cannot always know the exact width of
+ the table without loading all columns in the model, the \c contentWidth is
+ usually an estimate based on the columns it has seen so far. This estimate
+ is recalculated whenever new columns are flicked into view, which means
+ that the content width can change dynamically.
- If you know up front what the width of the table will be, assign a value
- to \c contentWidth explicitly, to avoid unnecessary calculations and
- updates to the TableView.
+ If you know what the width of the table will be, assign a value to
+ \c contentWidth, to avoid unnecessary calculations and updates to the
+ TableView.
- \sa contentHeight
+ \sa contentHeight, columnWidthProvider
*/
/*!
\qmlproperty real QtQuick::TableView::contentHeight
- This property holds the height of the \l view, which is also
- the height of the table (including margins). As a TableView cannot
- always know the exact height of the table without loading all rows
- in the model, the \c contentHeight is usually an estimated height
- based on the rows it has seen so far. This estimate is recalculated
- whenever new rows are flicked into view, which means that the content height
- can change dynamically.
+ This property holds the table height required to accommodate the number of
+ rows in the data model. This is usually not the same as the \c height of the
+ \c view, which means that the table's height could be larger or smaller than the
+ viewport height. As a TableView cannot always know the exact height of the
+ table without loading all rows in the model, the \c contentHeight is
+ usually an estimate based on the rows it has seen so far. This estimate is
+ recalculated whenever new rows are flicked into view, which means that
+ the content height can change dynamically.
- If you know up front what the height of the table will be, assign a
- value to \c contentHeight explicitly, to avoid unnecessary calculations and
- updates to the TableView.
+ If you know what the height of the table will be, assign a
+ value to \c contentHeight, to avoid unnecessary calculations and updates to
+ the TableView.
- \sa contentWidth
+ \sa contentWidth, rowHeightProvider
*/
/*!
@@ -329,7 +332,7 @@
Responding to changes in the model are batched so that they are handled
only once per frame. This means the TableView delays showing any changes
while a script is being run. The same is also true when changing
- properties such as \l rowSpacing or \l {Item::anchors.leftMargin}{leftMargin}.
+ properties, such as \l rowSpacing or \l{Item::anchors.leftMargin}{leftMargin}.
This method forces the TableView to immediately update the layout so
that any recent changes take effect.
@@ -366,9 +369,9 @@
item has been taken out of the pool and placed inside the content view,
and the model properties such as index, row, and column have been updated.
- Other properties that are not provided by the model does not change when an item
- is reused. You should avoid storing any state inside a delegate, but if you do,
- manually reset that state on receiving this signal.
+ Other properties that are not provided by the model does not change when an
+ item is reused. You should avoid storing any state inside a delegate, but if
+ you do, manually reset that state on receiving this signal.
This signal is emitted when the item is reused, and not the first time the
item is created.
@@ -706,9 +709,8 @@ void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable()
void QQuickTableViewPrivate::forceLayout()
{
- columnRowPositionsInvalid = true;
clearEdgeSizeCache();
- RebuildOptions rebuildOptions = RebuildOption::None;
+ RebuildOptions rebuildOptions = RebuildOption::LayoutOnly;
// Go through all columns from first to last, find the columns that used
// to be hidden and not loaded, and check if they should become visible
@@ -747,8 +749,7 @@ void QQuickTableViewPrivate::forceLayout()
break;
}
- if (rebuildOptions)
- scheduleRebuildTable(rebuildOptions);
+ scheduleRebuildTable(rebuildOptions);
if (polishing) {
qWarning() << "TableView::forceLayout(): Cannot do an immediate re-layout during an ongoing layout!";
@@ -1192,7 +1193,6 @@ void QQuickTableViewPrivate::relayoutTable()
void QQuickTableViewPrivate::relayoutTableItems()
{
qCDebug(lcTableViewDelegateLifecycle);
- columnRowPositionsInvalid = false;
qreal nextColumnX = loadedTableOuterRect.x();
qreal nextRowY = loadedTableOuterRect.y();
@@ -1398,6 +1398,22 @@ void QQuickTableViewPrivate::processLoadRequest()
void QQuickTableViewPrivate::processRebuildTable()
{
+ Q_Q(QQuickTableView);
+
+ if (rebuildState == RebuildState::Begin) {
+ if (Q_UNLIKELY(lcTableViewDelegateLifecycle().isDebugEnabled())) {
+ qCDebug(lcTableViewDelegateLifecycle()) << "begin rebuild:" << q;
+ if (rebuildOptions & RebuildOption::All)
+ qCDebug(lcTableViewDelegateLifecycle()) << "RebuildOption::All, options:" << rebuildOptions;
+ else if (rebuildOptions & RebuildOption::ViewportOnly)
+ qCDebug(lcTableViewDelegateLifecycle()) << "RebuildOption::ViewportOnly, options:" << rebuildOptions;
+ else if (rebuildOptions & RebuildOption::LayoutOnly)
+ qCDebug(lcTableViewDelegateLifecycle()) << "RebuildOption::LayoutOnly, options:" << rebuildOptions;
+ else
+ Q_TABLEVIEW_UNREACHABLE(rebuildOptions);
+ }
+ }
+
moveToNextRebuildState();
if (rebuildState == RebuildState::LoadInitalTable) {
@@ -1408,12 +1424,11 @@ void QQuickTableViewPrivate::processRebuildTable()
if (rebuildState == RebuildState::VerifyTable) {
if (loadedItems.isEmpty()) {
- qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model, all rows or columns hidden, or no delegate";
+ qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded!";
rebuildState = RebuildState::Done;
+ } else if (!moveToNextRebuildState()) {
return;
}
- if (!moveToNextRebuildState())
- return;
}
if (rebuildState == RebuildState::LayoutTable) {
@@ -1453,6 +1468,7 @@ void QQuickTableViewPrivate::processRebuildTable()
}
Q_TABLEVIEW_ASSERT(rebuildState == RebuildState::Done, int(rebuildState));
+ qCDebug(lcTableViewDelegateLifecycle()) << "rebuild complete:" << q;
}
bool QQuickTableViewPrivate::moveToNextRebuildState()
@@ -1462,7 +1478,13 @@ bool QQuickTableViewPrivate::moveToNextRebuildState()
// that the current state is not yet done.
return false;
}
- rebuildState = RebuildState(int(rebuildState) + 1);
+
+ if (rebuildState == RebuildState::Begin
+ && rebuildOptions.testFlag(RebuildOption::LayoutOnly))
+ rebuildState = RebuildState::LayoutTable;
+ else
+ rebuildState = RebuildState(int(rebuildState) + 1);
+
qCDebug(lcTableViewDelegateLifecycle()) << int(rebuildState);
return true;
}
@@ -1524,26 +1546,45 @@ void QQuickTableViewPrivate::beginRebuildTable()
loadedRows.clear();
loadedTableOuterRect = QRect();
loadedTableInnerRect = QRect();
- columnRowPositionsInvalid = false;
clearEdgeSizeCache();
+ if (!model) {
+ qCDebug(lcTableViewDelegateLifecycle()) << "no model found, leaving table empty";
+ return;
+ }
+
+ if (model->count() == 0) {
+ qCDebug(lcTableViewDelegateLifecycle()) << "empty model found, leaving table empty";
+ return;
+ }
+
+ if (tableModel && !tableModel->delegate()) {
+ qCDebug(lcTableViewDelegateLifecycle()) << "no delegate found, leaving table empty";
+ return;
+ }
+
if (topLeft.x() == kEdgeIndexAtEnd || topLeft.y() == kEdgeIndexAtEnd) {
- // No visible columns or rows, so nothing to load
+ qCDebug(lcTableViewDelegateLifecycle()) << "no visible rows or columns, leaving table empty";
return;
}
- loadInitialTopLeftItem(topLeft, topLeftPos);
+ // Load top-left item. After loaded, loadItemsInsideRect() will take
+ // care of filling out the rest of the table.
+ loadRequest.begin(topLeft, topLeftPos, QQmlIncubator::AsynchronousIfNested);
+ processLoadRequest();
loadAndUnloadVisibleEdges();
}
void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
{
- if (rowHeightProvider.isUndefined() || columnWidthProvider.isUndefined()) {
+ if (rebuildOptions.testFlag(RebuildOption::LayoutOnly)
+ || rowHeightProvider.isUndefined() || columnWidthProvider.isUndefined()) {
// Since we don't have both size providers, we need to calculate the
// size of each row and column based on the size of the delegate items.
// This couldn't be done while we were loading the initial rows and
// columns, since during the process, we didn't have all the items
- // available yet for the calculation. So we do it now.
+ // available yet for the calculation. So we do it now. The exception
+ // is if we specifically only requested a relayout.
relayoutTable();
}
@@ -1552,19 +1593,6 @@ void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
updateContentHeight();
}
-void QQuickTableViewPrivate::loadInitialTopLeftItem(const QPoint &cell, const QPointF &pos)
-{
- Q_TABLEVIEW_ASSERT(loadedItems.isEmpty(), "");
-
- if (tableModel && !tableModel->delegate())
- return;
-
- // Load top-left item. After loaded, loadItemsInsideRect() will take
- // care of filling out the rest of the table.
- loadRequest.begin(cell, pos, QQmlIncubator::AsynchronousIfNested);
- processLoadRequest();
-}
-
void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
{
qCDebug(lcTableViewDelegateLifecycle) << edge;
@@ -1701,16 +1729,10 @@ void QQuickTableViewPrivate::scheduleRebuildTable(RebuildOptions options) {
return;
}
- rebuildScheduled = true;
scheduledRebuildOptions |= options;
q_func()->polish();
}
-void QQuickTableViewPrivate::invalidateColumnRowPositions() {
- columnRowPositionsInvalid = true;
- q_func()->polish();
-}
-
void QQuickTableViewPrivate::updatePolish()
{
// Whenever something changes, e.g viewport moves, spacing is set to a
@@ -1743,19 +1765,12 @@ void QQuickTableViewPrivate::updatePolish()
if (loadedItems.isEmpty())
return;
- if (columnRowPositionsInvalid) {
- relayoutTable();
- updateAverageEdgeSize();
- updateContentWidth();
- updateContentHeight();
- }
-
loadAndUnloadVisibleEdges();
}
void QQuickTableViewPrivate::fixup(QQuickFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent)
{
- if (rebuildScheduled || rebuildState != RebuildState::Done)
+ if (scheduledRebuildOptions || rebuildState != RebuildState::Done)
return;
QQuickFlickablePrivate::fixup(data, minExtent, maxExtent);
@@ -1847,18 +1862,22 @@ void QQuickTableViewPrivate::syncWithPendingChanges()
void QQuickTableViewPrivate::syncRebuildOptions()
{
- if (!rebuildScheduled)
+ if (!scheduledRebuildOptions)
return;
rebuildState = RebuildState::Begin;
rebuildOptions = scheduledRebuildOptions;
scheduledRebuildOptions = RebuildOption::None;
- rebuildScheduled = false;
- if (loadedItems.isEmpty()) {
- // If we have no items from before, we cannot just rebuild the viewport, but need
- // to rebuild everything, since we have no top-left loaded item to start from.
+ if (loadedItems.isEmpty())
rebuildOptions.setFlag(RebuildOption::All);
+
+ // Some options are exclusive:
+ if (rebuildOptions.testFlag(RebuildOption::All)) {
+ rebuildOptions.setFlag(RebuildOption::ViewportOnly, false);
+ rebuildOptions.setFlag(RebuildOption::LayoutOnly, false);
+ } else if (rebuildOptions.testFlag(RebuildOption::ViewportOnly)) {
+ rebuildOptions.setFlag(RebuildOption::LayoutOnly, false);
}
}
@@ -2072,7 +2091,7 @@ void QQuickTableView::setRowSpacing(qreal spacing)
return;
d->cellSpacing.setHeight(spacing);
- d->invalidateColumnRowPositions();
+ d->scheduleRebuildTable(QQuickTableViewPrivate::RebuildOption::LayoutOnly);
emit rowSpacingChanged();
}
@@ -2090,7 +2109,7 @@ void QQuickTableView::setColumnSpacing(qreal spacing)
return;
d->cellSpacing.setWidth(spacing);
- d->invalidateColumnRowPositions();
+ d->scheduleRebuildTable(QQuickTableViewPrivate::RebuildOption::LayoutOnly);
emit columnSpacingChanged();
}
@@ -2242,7 +2261,7 @@ void QQuickTableView::viewportMoved(Qt::Orientations orientation)
d->scheduleRebuildTable(options);
}
- if (d->rebuildScheduled) {
+ if (d->scheduledRebuildOptions) {
// No reason to do anything, since we're about to rebuild the whole table anyway.
// Besides, calling updatePolish, which will start the rebuild, can easily cause
// binding loops to happen since we usually end up modifying the geometry of the
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index f2fef0d774..6bbfd4e2d6 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -188,10 +188,11 @@ public:
enum class RebuildOption {
None = 0,
- ViewportOnly = 0x1,
- CalculateNewTopLeftRow = 0x2,
- CalculateNewTopLeftColumn = 0x4,
- All = 0x8,
+ LayoutOnly = 0x1,
+ ViewportOnly = 0x2,
+ CalculateNewTopLeftRow = 0x4,
+ CalculateNewTopLeftColumn = 0x8,
+ All = 0x10,
};
Q_DECLARE_FLAGS(RebuildOptions, RebuildOption)
@@ -246,10 +247,8 @@ public:
QQmlTableInstanceModel::ReusableFlag reusableFlag = QQmlTableInstanceModel::Reusable;
bool blockItemCreatedCallback = false;
- bool columnRowPositionsInvalid = false;
bool layoutWarningIssued = false;
bool polishing = false;
- bool rebuildScheduled = true;
QJSValue rowHeightProvider;
QJSValue columnWidthProvider;
@@ -342,7 +341,6 @@ public:
void releaseLoadedItems(QQmlTableInstanceModel::ReusableFlag reusableFlag);
void unloadItem(const QPoint &cell);
- void loadInitialTopLeftItem(const QPoint &cell, const QPointF &pos);
void loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode);
void unloadEdge(Qt::Edge edge);
void loadAndUnloadVisibleEdges();
@@ -357,7 +355,6 @@ public:
void layoutAfterLoadingInitialTable();
void scheduleRebuildTable(QQuickTableViewPrivate::RebuildOptions options);
- void invalidateColumnRowPositions();
int resolveImportVersion();
void createWrapperModel();
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 63f3b91b82..7a04c2146c 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -183,7 +183,6 @@ void QQmlQtQuick2Module::defineModule()
QQuick_initializeProviders();
QQuickUtilModule::defineModule();
- QQmlEnginePrivate::defineQtQuick2Module();
QQuickItemsModule::defineModule();
qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 5337bfd640..527274e6be 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -41,7 +41,6 @@
#include <private/qquickvaluetypes_p.h>
#include <private/qquickapplication_p.h>
#include <private/qqmlglobal_p.h>
-#include <private/qv8engine_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/qdesktopservices.h>
@@ -274,7 +273,7 @@ public:
return QMatrix4x4();
}
- static QFont fontFromObject(QQmlV4Handle object, QV4::ExecutionEngine *v4, bool *ok)
+ static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
{
if (ok)
*ok = false;
@@ -373,7 +372,7 @@ public:
return retn;
}
- static QMatrix4x4 matrix4x4FromObject(QQmlV4Handle object, QV4::ExecutionEngine *v4, bool *ok)
+ static QMatrix4x4 matrix4x4FromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
{
if (ok)
*ok = false;
@@ -639,7 +638,7 @@ public:
return false;
}
- bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v) override
+ bool variantFromJsObject(int type, const QV4::Value &object, QV4::ExecutionEngine *v4, QVariant *v) override
{
QV4::Scope scope(v4);
#ifndef QT_NO_DEBUG