aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc13
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp3
-rw-r--r--src/quick/items/qquickitem.cpp9
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp4
-rw-r--r--src/quick/items/qquicktableview.cpp4
-rw-r--r--src/quick/items/qquicktextcontrol.cpp2
-rw-r--r--src/quick/items/qquicktextedit.cpp13
-rw-r--r--src/quick/items/qquicktextinput.cpp16
-rw-r--r--src/quick/items/qquicktreeview.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp11
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp7
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h2
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h3
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp3
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp6
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp33
-rw-r--r--src/quick/util/qquickapplication.cpp2
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp5
-rw-r--r--src/quick/util/qquickforeignutils.cpp78
-rw-r--r--src/quick/util/qquickpath.cpp2
-rw-r--r--src/quick/util/qquicksvgparser.cpp12
-rw-r--r--src/quick/util/qquicktransition.cpp67
23 files changed, 220 insertions, 81 deletions
diff --git a/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc b/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
index 1ce20de5f0..876723d66e 100644
--- a/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
@@ -8,10 +8,10 @@
anti-patterns.
\e qmllint is a tool shipped with Qt, that verifies the syntatic validity of
-QML files.
-It also warns about some QML anti-patterns. If you want to disable a specific
-warning type, you can find the appropriate flag for doing so by passing
-\c{--help} on the command line.
+QML files. You can \l{Using qmllint with CMake}{integrate qmllint into your build system}
+for ease of use. It also warns about some QML anti-patterns. If you want to
+disable a specific warning type, you can find the appropriate flag for doing so
+by passing \c{--help} on the command line.
By default, some issues will result in warnings that will be printed and result
in a non-zero exit code.
@@ -49,6 +49,11 @@ qmllint can warn you about code that cannot be compiled by \l{qmlsc}.
These warnigs are not enabled by default. In order to enable them specify
\c{--compiler warning} or adjust your settings file accordingly.
+\section2 Using qmllint with CMake
+For projects using the \l{qt6_add_qml_module}{qt_add_qml_module()} CMake API for creating QML
+modules, \l{Linting QML sources}{convenience targets} such as \c all_qmllint are created
+automatically. These run qmllint on all the QML files of a specific module or of the project.
+
\section2 Marking components and properties as deprecated
qmllint allows you to mark both properties and components as deprecated:
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index 865fb8bf11..b0c55b4653 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -430,6 +430,9 @@ void QQuickAccessibleAttached::setIgnored(bool ignored)
{
if (this->ignored() != ignored && item()) {
item()->d_func()->isAccessible = !ignored;
+ QAccessibleEvent event(item(),
+ ignored ? QAccessible::ObjectDestroyed : QAccessible::ObjectCreated);
+ QAccessible::updateAccessibility(&event);
emit ignoredChanged();
}
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index ec339ccc3b..239b512b9b 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6425,10 +6425,11 @@ void QQuickItem::setVisible(bool v)
This property holds whether the item receives mouse and keyboard events.
By default this is true.
- Setting this property directly affects the \c enabled value of child
- items. When set to \c false, the \c enabled values of all child items also
- become \c false. When set to \c true, the \c enabled values of child items
- are returned to \c true, unless they have explicitly been set to \c false.
+ Setting this property affects the \e effective \c enabled states of child items.
+ When an item's parent is not enabled, the (child) item is effectively disabled and
+ does not receive input events, even if its own \c enabled property is explicitly
+ set to \c true. The child \c enabled property keeps its value, but becomes
+ effective again only if all its ancestor items are enabled.
Setting this property to \c false automatically causes \l activeFocus to be
set to \c false, and this item will no longer receive keyboard events.
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index c1188ac4d7..684aa8f98e 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -42,7 +42,7 @@ public:
};
-class Q_AUTOTEST_EXPORT QQuickItemViewChangeSet
+class Q_QUICK_EXPORT QQuickItemViewChangeSet
{
public:
QQuickItemViewChangeSet();
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index b0b99334a2..33d801a2a3 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -660,8 +660,8 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints
for (const QEventPoint &p : std::as_const(touchPoints)) {
if (p.state() == QEventPoint::State::Released)
continue;
- const QPointF &currentPos = p.scenePosition();
- const QPointF &startPos = p.scenePressPosition();
+ const QPointF currentPos = mapFromScene(p.scenePosition());
+ const QPointF startPos = mapFromScene(p.scenePressPosition());
if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
offerGrab = true;
else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 3cc63cece0..dbbdfec6cc 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -4866,8 +4866,8 @@ bool QQuickTableViewPrivate::canEdit(const QModelIndex tappedIndex, bool warn)
return false;
}
- if (auto const qaim = model->abstractItemModel()) {
- if (!(qaim->flags(tappedIndex) & Qt::ItemIsEditable)) {
+ if (auto const sourceModel = qaim(modelImpl())) {
+ if (!(sourceModel->flags(tappedIndex) & Qt::ItemIsEditable)) {
if (warn)
qmlWarning(q) << "cannot edit: QAbstractItemModel::flags(index) doesn't contain Qt::ItemIsEditable";
return false;
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 510ece726a..c5b87a7c30 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -742,7 +742,7 @@ void QQuickTextControl::processEvent(QEvent *e, const QTransform &transform)
case QEvent::ShortcutOverride:
if (d->interactionFlags & Qt::TextEditable) {
- QKeyEvent* ke = static_cast<QKeyEvent *>(e);
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
ke->setAccepted(isCommonTextEditShortcut(ke));
}
break;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 4471d6e4b9..57c12d2825 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1751,12 +1751,15 @@ QRectF QQuickTextEdit::cursorRectangle() const
bool QQuickTextEdit::event(QEvent *event)
{
Q_D(QQuickTextEdit);
- if (event->type() == QEvent::ShortcutOverride) {
- d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
- if (event->isAccepted())
- return true;
+ bool state = QQuickImplicitSizeItem::event(event);
+ if (event->type() == QEvent::ShortcutOverride && !event->isAccepted()) {
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(this);
+ if (!itemPriv->extra.isAllocated() || !itemPriv->extra->keyHandler) {
+ d->control->processEvent(event, QPointF(-d->xoff, -d->yoff));
+ }
+ state = true;
}
- return QQuickImplicitSizeItem::event(event);
+ return state;
}
/*!
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 08713eb026..495f99505f 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -49,6 +49,13 @@ Q_LOGGING_CATEGORY(lcQuickTextInput, "qt.quick.textInput")
and setting \l echoMode to an appropriate value enables TextInput to be used for
a password input field.
+ To react to the user accepting text via the Return or Enter keys, handle
+ the \l accepted() signal. When Return or Enter are pressed and the text
+ input loses focus, \l editingFinished() will be emitted. When the text is
+ edited in any way by the user, \l textEdited() is emitted. These signals
+ \l {Property change signals}{should be preferred} over \c textChanged()
+ in most cases.
+
On \macos, the Up/Down key bindings for Home/End are explicitly disabled.
If you want such bindings (on any platform), you will need to construct them in QML.
@@ -96,7 +103,8 @@ void QQuickTextInput::componentComplete()
the \l preeditText property. To get whole text displayed in the TextInput
use \l displayText property.
- \sa clear(), displayText, preeditText
+ \sa clear(), displayText, preeditText, accepted(), editingFinished(),
+ textEdited()
*/
QString QQuickTextInput::text() const
{
@@ -1184,6 +1192,8 @@ bool QQuickTextInput::hasAcceptableInput() const
Note that if there is a \l validator or \l inputMask set on the text
input, the signal will only be emitted if the input is in an acceptable
state.
+
+ \sa editingFinished(), textEdited()
*/
/*!
@@ -1195,6 +1205,8 @@ bool QQuickTextInput::hasAcceptableInput() const
inputMask set on the text input and enter/return is pressed, this
signal will only be emitted if the input follows
the inputMask and the validator returns an acceptable state.
+
+ \sa accepted(), textEdited()
*/
/*!
@@ -1204,6 +1216,8 @@ bool QQuickTextInput::hasAcceptableInput() const
This signal is emitted whenever the text is edited. Unlike \c textChanged(),
this signal is not emitted when the text is changed programmatically, for example,
by changing the value of the \c text property or by calling \c clear().
+
+ \sa accepted(), editingFinished()
*/
#if QT_CONFIG(im)
diff --git a/src/quick/items/qquicktreeview.cpp b/src/quick/items/qquicktreeview.cpp
index 88373a1706..17e21a75f4 100644
--- a/src/quick/items/qquicktreeview.cpp
+++ b/src/quick/items/qquicktreeview.cpp
@@ -650,8 +650,10 @@ void QQuickTreeView::keyPressEvent(QKeyEvent *event)
break;
}
- if (!event->isAccepted())
+ if (!event->isAccepted()) {
+ event->accept();
QQuickTableView::keyPressEvent(event);
+ }
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index eee8316d05..cc229708f1 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -371,6 +371,17 @@ QSGRenderNode::RenderState::~RenderState()
}
/*!
+ \class QSGRenderNode::RenderState
+ \brief Provides information about the projection matrix and clipping.
+ \inmodule QtQuick
+
+ The render state contains information for the renderer when invoking
+ commands to the scenegraph backends.
+
+ \sa QSGRenderNode::render()
+ */
+
+/*!
\fn const QMatrix4x4 *QSGRenderNode::RenderState::projectionMatrix() const
\return pointer to the current projection matrix.
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 64f862f948..b0ab978908 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -9,7 +9,8 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcSgText, "qt.scenegraph.text")
-qint64 QSGDistanceFieldGlyphNode::m_totalAllocation = 0;
+// all SG glyph vertices and indices; only for qCDebug metrics
+static std::atomic<qint64> s_totalAllocation = 0;
QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGRenderContext *context)
: m_glyphNodeType(RootGlyphNode)
@@ -314,9 +315,9 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
}
}
- m_totalAllocation += vp.size() * sizeof(QSGGeometry::TexturedPoint2D) + ip.size() * sizeof(quint16);
+ s_totalAllocation += vp.size() * sizeof(QSGGeometry::TexturedPoint2D) + ip.size() * sizeof(quint16);
qCDebug(lcSgText) << "allocating for" << vp.size() << "vtx (reserved" << likelyGlyphCount * 4 << "):" << vp.size() * sizeof(QSGGeometry::TexturedPoint2D)
- << "bytes;" << ip.size() << "idx:" << ip.size() * sizeof(quint16) << "bytes; total bytes so far" << m_totalAllocation;
+ << "bytes;" << ip.size() << "idx:" << ip.size() * sizeof(quint16) << "bytes; total bytes so far" << s_totalAllocation;
g->allocate(vp.size(), ip.size());
memcpy(g->vertexDataAsTexturedPoint2D(), vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
memcpy(g->indexDataAsUShort(), ip.constData(), ip.size() * sizeof(quint16));
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index d92bf0a836..04b17f0ab7 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -84,8 +84,6 @@ private:
uint m_dirtyGeometry: 1;
uint m_dirtyMaterial: 1;
-
- static qint64 m_totalAllocation; // all SG glyph vertices and indices; only for qCDebug metrics
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 73d30ffb6b..bbd169708a 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -105,6 +105,9 @@ WM_Obscure = QEvent::User + 1,
// (updatePaintNode())
WM_RequestSync = QEvent::User + 2,
+// Passed from the RL to the RT when a window is exposed
+WM_Exposed = QEvent::User + 3,
+
// Passed by the RL to the RT to free up maybe release SG and GL contexts
// if no windows are rendering.
WM_TryRelease = QEvent::User + 4,
diff --git a/src/quick/scenegraph/qsgrhishadereffectnode.cpp b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
index f1db5804e6..4c9facbb57 100644
--- a/src/quick/scenegraph/qsgrhishadereffectnode.cpp
+++ b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
@@ -9,6 +9,9 @@
#include <private/qsgplaintexture_p.h>
#include <QtGui/private/qshaderdescription_p.h>
#include <QQmlFile>
+
+#include <QtGui/qquaternion.h>
+
#include <QFile>
#include <QFileSelector>
#include <QMutexLocker>
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index 57cd51f171..25b7b620e0 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -1334,7 +1334,11 @@ QImage QSGRhiSupport::grabOffscreen(QQuickWindow *window)
// There was no rendercontrol which means a custom render target
// should not be set either. Set our own, temporarily.
- window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(rt.data()));
+ auto renderTarget = QQuickRenderTarget::fromRhiRenderTarget(rt.data());
+ // Pass on the scale factor. No need to use effectiveDevicePixelRatio(),
+ // because there is no rendercontrol anyway.
+ renderTarget.setDevicePixelRatio(window->devicePixelRatio());
+ window->setRenderTarget(renderTarget);
QRhiCommandBuffer *cb = nullptr;
if (rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess) {
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index d2a160c420..fc92673d8e 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -335,6 +335,17 @@ bool QSGRenderThread::event(QEvent *e)
return true; }
+
+ case WM_Exposed: {
+ qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_Exposed");
+
+ mutex.lock();
+ window = static_cast<WMWindowEvent *>(e)->window;
+ waitCondition.wakeOne();
+ mutex.unlock();
+
+ return true; }
+
case WM_RequestSync: {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_RequestSync");
WMSyncEvent *se = static_cast<WMSyncEvent *>(e);
@@ -632,8 +643,14 @@ void QSGRenderThread::syncAndRender()
// An update request could still be delivered right before we get an
// unexpose. With Vulkan on Windows for example attempting to render
// leads to failures at this stage since the surface size is already 0.
- if (effectiveOutputSize.isEmpty())
+ if (effectiveOutputSize.isEmpty()) {
+ if (syncRequested) {
+ mutex.lock();
+ waitCondition.wakeOne();
+ mutex.unlock();
+ }
return;
+ }
const QSize previousOutputSize = cd->swapchain->currentPixelSize();
if (previousOutputSize != effectiveOutputSize || cd->swapchainJustBecameRenderable) {
@@ -1249,10 +1266,6 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
}
}
- // set this early as we'll be rendering shortly anyway and this avoids
- // specialcasing exposure in polishAndSync.
- w->thread->window = window;
-
#ifndef QT_NO_DEBUG
if (w->window->width() <= 0 || w->window->height() <= 0
|| (w->window->isTopLevel() && !w->window->geometry().intersects(w->window->screen()->availableGeometry()))) {
@@ -1271,6 +1284,10 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
if (!w->thread->isRunning()) {
qCDebug(QSG_LOG_RENDERLOOP, "- starting render thread");
+ // set this early as we'll be rendering shortly anyway and this avoids
+ // specialcasing exposure in polishAndSync.
+ w->thread->window = window;
+
if (!w->thread->rhi) {
QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
if (!w->thread->offscreenSurface)
@@ -1295,6 +1312,12 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
} else {
qCDebug(QSG_LOG_RENDERLOOP, "- render thread already running");
+
+ // set w->thread->window here too, but using an event so it's thread-safe
+ w->thread->mutex.lock();
+ w->thread->postEvent(new WMWindowEvent(w->window, QEvent::Type(WM_Exposed)));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ w->thread->mutex.unlock();
}
polishAndSync(w, true);
diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp
index 2cb8fe36ba..f56533e355 100644
--- a/src/quick/util/qquickapplication.cpp
+++ b/src/quick/util/qquickapplication.cpp
@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
\qml
Timer {
interval: 1000; repeat: true
- active: Application.state === Qt.Qt.ApplicationActive
+ active: Application.state === Qt.ApplicationActive
onTriggered: imageFetcher.fetchLatestImages()
}
\endqml
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index 6fc50aaa5c..9bd2efb279 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -899,7 +899,9 @@ void QQuickDeliveryAgentPrivate::deliverKeyEvent(QKeyEvent *e)
e->isAutoRepeat(), e->count());
do {
- e->accept();
+ Q_ASSERT(e->type() != QEvent::ShortcutOverride || !e->isAccepted());
+ if (e->type() != QEvent::ShortcutOverride)
+ e->accept();
QCoreApplication::sendEvent(item, e);
} while (!e->isAccepted() && (item = item->parentItem()));
}
@@ -1055,6 +1057,7 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
if (subtreeHoverEnabled) {
hoveredLeafItemFound = false;
+ QQuickPointerHandlerPrivate::deviceDeliveryTargets(QPointingDevice::primaryPointingDevice()).clear();
deliverHoverEventRecursive(rootItem, scenePos, lastScenePos, modifiers, timestamp);
}
diff --git a/src/quick/util/qquickforeignutils.cpp b/src/quick/util/qquickforeignutils.cpp
index 34b3225abe..6ca5a42ade 100644
--- a/src/quick/util/qquickforeignutils.cpp
+++ b/src/quick/util/qquickforeignutils.cpp
@@ -19,32 +19,58 @@ QT_BEGIN_NAMESPACE
The following properties are available:
\list
- \li \l bool \c eventPoint.accepted: see also \l QEventPoint::accepted
- \li \l PointerDevice \c eventPoint.device: see also \l QEventPoint::device
- \li \l size \c eventPoint.ellipseDiameters: see also \l QEventPoint::ellipseDiameters
- \li \l point \c eventPoint.globalGrabPosition: see also \l QEventPoint::globalGrabPosition
- \li \l point \c eventPoint.globalLastPosition: see also \l QEventPoint::globalLastPosition
- \li \l point \c eventPoint.globalPosition: see also \l QEventPoint::globalPosition
- \li \l point \c eventPoint.globalPressPosition: see also \l QEventPoint::globalPressPosition
- \li \l bool \c eventPoint.grabPosition: see also \l QEventPoint::grabPosition
- \li \l int \c eventPoint.id: see also \l QEventPoint::id
- \li \l point \c eventPoint.lastPosition: see also \l QEventPoint::lastPosition
- \li \l ulong \c eventPoint.lastTimestamp: see also \l QEventPoint::lastTimestamp
- \li \l point \c eventPoint.position: see also \l QEventPoint::position
- \li \l point \c eventPoint.pressPosition: see also \l QEventPoint::pressPosition
- \li \l int \c eventPoint.pressTimestamp: see also \l QEventPoint::pressTimestamp
- \li \l real \c eventPoint.pressure: see also \l QEventPoint::pressure
- \li \l real \c eventPoint.rotation: see also \l QEventPoint::rotation
- \li \l point \c eventPoint.sceneGrabPosition: see also \l QEventPoint::sceneGrabPosition
- \li \l point \c eventPoint.sceneLastPosition: see also \l QEventPoint::sceneLastPosition
- \li \l point \c eventPoint.scenePosition: see also \l QEventPoint::scenePosition
- \li \l ulong \c eventPoint.pressTimestamp: see also \l QEventPoint::pressTimestamp
- \li \l point \c eventPoint.scenePressPosition: see also \l QEventPoint::scenePressPosition
- \li \l {QML Enumerations}{enumeration} \c eventPoint.state: see also \l QEventPoint::state
- \li \l real \c eventPoint.timeHeld: see also \l QEventPoint::timeHeld
- \li \l ulong \c eventPoint.timestamp: see also \l QEventPoint::timestamp
- \li \l pointingDeviceUniqueId \c eventPoint.uniqueId: see also \l QEventPoint::uniqueId
- \li \l vector2d \c eventPoint.velocity: see also \l QEventPoint::velocity
+ \li \l bool \c eventPoint.accepted \br
+ See also \l {QEventPoint::accepted}.
+ \li \l PointerDevice \c eventPoint.device \br
+ See also \l {QEventPoint::device}.
+ \li \l size \c eventPoint.ellipseDiameters \br
+ See also \l {QEventPoint::ellipseDiameters}.
+ \li \l point \c eventPoint.globalGrabPosition \br
+ See also \l {QEventPoint::globalGrabPosition}.
+ \li \l point \c eventPoint.globalLastPosition \br
+ See also \l {QEventPoint::globalLastPosition}.
+ \li \l point \c eventPoint.globalPosition \br
+ See also \l {QEventPoint::globalPosition}.
+ \li \l point \c eventPoint.globalPressPosition \br
+ See also \l {QEventPoint::globalPressPosition}.
+ \li \l bool \c eventPoint.grabPosition \br
+ See also \l {QEventPoint::grabPosition}.
+ \li \l int \c eventPoint.id \br
+ See also \l {QEventPoint::id}.
+ \li \l point \c eventPoint.lastPosition \br
+ See also \l {QEventPoint::lastPosition}.
+ \li \l ulong \c eventPoint.lastTimestamp \br
+ See also \l {QEventPoint::lastTimestamp}.
+ \li \l point \c eventPoint.position \br
+ See also \l {QEventPoint::position}.
+ \li \l point \c eventPoint.pressPosition \br
+ See also \l {QEventPoint::pressPosition}.
+ \li \l int \c eventPoint.pressTimestamp \br
+ See also \l {QEventPoint::pressTimestamp}.
+ \li \l real \c eventPoint.pressure \br
+ See also \l {QEventPoint::pressure}.
+ \li \l real \c eventPoint.rotation \br
+ See also \l {QEventPoint::rotation}.
+ \li \l point \c eventPoint.sceneGrabPosition \br
+ See also \l {QEventPoint::sceneGrabPosition}.
+ \li \l point \c eventPoint.sceneLastPosition \br
+ See also \l {QEventPoint::sceneLastPosition}.
+ \li \l point \c eventPoint.scenePosition \br
+ See also \l {QEventPoint::scenePosition}.
+ \li \l ulong \c eventPoint.pressTimestamp \br
+ See also \l {QEventPoint::pressTimestamp}.
+ \li \l point \c eventPoint.scenePressPosition \br
+ See also \l {QEventPoint::scenePressPosition}.
+ \li \l {QML Enumerations}{enumeration} \c eventPoint.state \br
+ See also \l {QEventPoint::state}.
+ \li \l real \c eventPoint.timeHeld \br
+ See also \l {QEventPoint::timeHeld}.
+ \li \l ulong \c eventPoint.timestamp \br
+ See also \l {QEventPoint::timestamp}.
+ \li \l pointingDeviceUniqueId \c eventPoint.uniqueId \br
+ See also \l {QEventPoint::uniqueId}.
+ \li \l vector2d \c eventPoint.velocity \br
+ See also \l {QEventPoint::velocity}.
\endlist
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 17529317d5..7562b74d46 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -1982,8 +1982,6 @@ void QQuickPathArc::addToPath(QPainterPath &path, const QQuickPathData &data)
{
const QPointF &startPoint = path.currentPosition();
const QPointF &endPoint = positionForCurve(data, startPoint);
- if (startPoint == endPoint)
- return;
QQuickSvgParser::pathArc(path,
_radiusX,
_radiusY,
diff --git a/src/quick/util/qquicksvgparser.cpp b/src/quick/util/qquicksvgparser.cpp
index 5f88805ef7..8cca5addbb 100644
--- a/src/quick/util/qquicksvgparser.cpp
+++ b/src/quick/util/qquicksvgparser.cpp
@@ -159,6 +159,10 @@ void QQuickSvgParser::pathArc(QPainterPath &path,
qreal y,
qreal curx, qreal cury)
{
+ // Check if the start point is equal to the end point.
+ if (QPointF(curx, cury) == QPointF(x, y))
+ return;
+
qreal sin_th, cos_th;
qreal a00, a01, a10, a11;
qreal x0, y0, x1, y1, xc, yc;
@@ -169,6 +173,14 @@ void QQuickSvgParser::pathArc(QPainterPath &path,
rx = qAbs(rx);
ry = qAbs(ry);
+ // Avoid nans and division by zero.
+ if (qFuzzyIsNull(rx) || qFuzzyIsNull(ry)) {
+ // https://www.w3.org/TR/SVG/paths.html#ArcOutOfRangeParameters says:
+ // "If either rx or ry is 0, then this arc is treated as a straight line
+ // segment (a "lineto") joining the endpoints."
+ path.lineTo(x, y);
+ return;
+ }
sin_th = qSin(qDegreesToRadians(x_axis_rotation));
cos_th = qCos(qDegreesToRadians(x_axis_rotation));
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index 09d92ddb36..3c5e847702 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -107,14 +107,20 @@ protected:
static qsizetype animation_count(QQmlListProperty<QQuickAbstractAnimation> *list);
static QQuickAbstractAnimation* animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos);
static void clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list);
- QList<QQuickAbstractAnimation *> animations;
+ static void removeLast_animation(QQmlListProperty<QQuickAbstractAnimation> *list);
+ static void replace_animation(
+ QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos,
+ QQuickAbstractAnimation *a);
+
+ QList<QPointer<QQuickAbstractAnimation>> animations;
};
void QQuickTransitionPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
{
QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
q->d_func()->animations.append(a);
- a->setDisableUserControl();
+ if (a)
+ a->setDisableUserControl();
}
qsizetype QQuickTransitionPrivate::animation_count(QQmlListProperty<QQuickAbstractAnimation> *list)
@@ -132,10 +138,25 @@ QQuickAbstractAnimation* QQuickTransitionPrivate::animation_at(QQmlListProperty<
void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list)
{
QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
- while (q->d_func()->animations.size()) {
- QQuickAbstractAnimation *firstAnim = q->d_func()->animations.at(0);
- q->d_func()->animations.removeAll(firstAnim);
- }
+ q->d_func()->animations.clear();
+}
+
+void QQuickTransitionPrivate::removeLast_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
+{
+ QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
+ q->d_func()->animations.removeLast();
+}
+
+void QQuickTransitionPrivate::replace_animation(
+ QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos, QQuickAbstractAnimation *a)
+{
+ QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
+ QQuickTransitionPrivate *d = q->d_func();
+ if (d->animations.length() <= pos)
+ d->animations.resize(pos + 1, nullptr);
+ d->animations[pos] = a;
+ if (a)
+ a->setDisableUserControl();
}
void QQuickTransitionInstance::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
@@ -240,15 +261,19 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
int start = d->reversed ? d->animations.size() - 1 : 0;
int end = d->reversed ? -1 : d->animations.size();
- QAbstractAnimationJob *anim = nullptr;
- for (int i = start; i != end;) {
- anim = d->animations.at(i)->transition(actions, after, direction, defaultTarget);
- if (anim) {
- if (d->animations.at(i)->threadingModel() == QQuickAbstractAnimation::RenderThread)
- anim = new QQuickAnimatorProxyJob(anim, d->animations.at(i));
- d->reversed ? group->prependAnimation(anim) : group->appendAnimation(anim);
- }
- d->reversed ? --i : ++i;
+ for (int i = start; i != end; d->reversed ? --i : ++i) {
+ QQuickAbstractAnimation *anim = d->animations.at(i);
+ if (!anim)
+ continue;
+
+ QAbstractAnimationJob *job = anim->transition(actions, after, direction, defaultTarget);
+ if (!job)
+ continue;
+
+ if (anim->threadingModel() == QQuickAbstractAnimation::RenderThread)
+ job = new QQuickAnimatorProxyJob(job, anim);
+
+ d->reversed ? group->prependAnimation(job) : group->appendAnimation(job);
}
group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward);
@@ -434,10 +459,14 @@ bool QQuickTransition::running() const
QQmlListProperty<QQuickAbstractAnimation> QQuickTransition::animations()
{
Q_D(QQuickTransition);
- return QQmlListProperty<QQuickAbstractAnimation>(this, &d->animations, QQuickTransitionPrivate::append_animation,
- QQuickTransitionPrivate::animation_count,
- QQuickTransitionPrivate::animation_at,
- QQuickTransitionPrivate::clear_animations);
+ return QQmlListProperty<QQuickAbstractAnimation>(
+ this, &d->animations,
+ QQuickTransitionPrivate::append_animation,
+ QQuickTransitionPrivate::animation_count,
+ QQuickTransitionPrivate::animation_at,
+ QQuickTransitionPrivate::clear_animations,
+ QQuickTransitionPrivate::replace_animation,
+ QQuickTransitionPrivate::removeLast_animation);
}
QT_END_NAMESPACE